Guild icon
swift-developers-japan
main / swift-2
話題が複数あるときの待避所
Avatar
omochimetaru 27-Apr-17 03:32 AM
@tarunon wt は、 Cat が Protocol に準拠した時の、witness-tableへのポインタ。
03:32
例えば Dog が Protocol に準拠した時 のテーブルは別に存在していて
Avatar
tarunon 27-Apr-17 03:32 AM
だから、呼び出せる関数はもう決まっていて
Avatar
omochimetaru 27-Apr-17 03:32 AM
でもその2つのテーブルの、エントリの並びは、 Protocolの定義に従って揃ってる。
Avatar
tarunon 27-Apr-17 03:32 AM
テーブルの探索は浅くて済むんだよね
Avatar
omochimetaru 27-Apr-17 03:32 AM
探索はしない。
03:32
インデックス番号だけ。
03:32
テーブルの2番目、とか、テーブルの3番目、とか (edited)
03:33
静的なインデックスにコンパイルされてる。
Avatar
tarunon 27-Apr-17 03:33 AM
じゃあfunc hoge<Foo: Protocol>(foo: Foo)と、fucn (foo: Protocol) だと
03:33
この関数の中で使われるfooが呼び出す関数は
03:33
テーブルの探索の有無の差が生まれる
Avatar
omochimetaru 27-Apr-17 03:34 AM
あ、いや、
03:34
後者の場合も、
03:34
Protocol 型の変数っていうのは
03:34
結局、 (x, wt, xt) の 3つのフィールドを持つ 特殊な型なんだよね (edited)
Avatar
tarunon 27-Apr-17 03:34 AM
んー
Avatar
omochimetaru 27-Apr-17 03:34 AM
だから結局同じ。
Avatar
tarunon 27-Apr-17 03:34 AM
おお
03:35
じゃあ僕が最初に言っていた
03:35
Protocol型の変数は暗黙的にGenerics型の変数と同じ状態になる?
03:35
というが既に存在している、ということ
Avatar
omochimetaru 27-Apr-17 03:35 AM
Associated Type が無い場合に限っては、YES (edited)
Avatar
tarunon 27-Apr-17 03:35 AM
おおお~
03:35
理解完了
03:35
あざっす
Avatar
omochimetaru 27-Apr-17 03:35 AM
逆に言うと、
03:35
Associated Typeがある場合でも
03:36
引数には渡す事が今もできるわけで
Avatar
tarunon 27-Apr-17 03:36 AM
そうだね
Avatar
omochimetaru 27-Apr-17 03:36 AM
その時にはさっきの3タプルになってるわけだから
03:36
そもそも既にExistentalのバイナリ表現はこの3タプルで
03:36
完成してるやんけ
03:36
っていうのが
03:36
# 導入 Swiftでは通常のプロトコルは変数の型として使用することができますが、 型パラメータ(associated type)を持つジェネリックなプロトコルの変数は作れません。 非ジェネリックな例 ```swift prot...
03:36
この記事で最終的にぶつかってる謎で
03:37
だから、パフォーマンスのために あえて やってないのかなあ?って話をした。
Avatar
tarunon 27-Apr-17 03:37 AM
ふーむ
03:37
構文が完成してなかっただけでは?という気もしている
Avatar
omochimetaru 27-Apr-17 03:37 AM
そうだね、SILの時点で表現可能な文法が無かったから、それもある。
03:38
技術的にはできるけど作らないといけない部品がいっぱいあるのは確かだからそれで止まってるだけなのかもしれない。
Avatar
ゆし 09-Jun-17 04:35 AM
namespaceを作りたいときってclassとstruct(or enum)どちらを使いますか?
struct API { private init() { } struct Request { private init() { } struct GetDayOfWeekStories: APIRequest {
(edited)
Avatar
rintaro 09-Jun-17 04:38 AM
case なし enum だとどうやってもインスタンス化できないので、 private init 書く必要ないから いいんじゃないかと思ってます。
🙂 1
Avatar
ゆし 09-Jun-17 04:40 AM
おお、たしかに (いま、private init() { fatalError() }くらいにした方がいいかなと思ってました)
Avatar
rintaro 09-Jun-17 04:43 AM
/// Namespace for diagnostics enum diag {} extension diag { // メンバー群 ...
実際にはすべてのメンバーを extension に実装することにより、 case を書けなくするということをやっています。
(edited)
Avatar
ゆし 09-Jun-17 04:48 AM
なるほど。 ありがとうございます。
Avatar
rinsuki 10-Jun-17 01:31 PM
Swiftの??って、もしかしてコンパイルすごい遅いんでしょうか
13:31
func apiErrorWithPromise(_ errorMsg: String? = nil, _ httpNumber: Int? = nil) -> Promise<Void>{ let errorMessage = "エラーメッセージ:\n"+(errorMsg ?? "不明なエラー(iMast)")+" ("+String(httpNumber ?? -1)+")\n\nエラーメッセージに従っても解決しない場合は、アプリを再起動してみてください。" return alertWithPromise( title: "APIエラー", message: errorMessage ) }
13:31
こういう関数があるのですが、この関数のコンパイルに30秒ほどかかってしまっていて
13:32
以前はerrorMessageに代入しているところをmessageに直接書いていたのですが、複雑すぎるとSwiftコンパイラに怒られてしまったので分けたのですが
13:33
他の似たような関数では遅くないので、??が原因なのかなあto
13:33
思ったのですが
Avatar
applideveloper 10-Jun-17 01:34 PM
?? あるケースとないケースで、計測してみては?
Avatar
rinsuki 10-Jun-17 01:34 PM
とりあえず??を!にしてみたところありえん早くなりました
Avatar
rintaro 10-Jun-17 01:34 PM
13:35
認識はされていますが、なかなか直りませんねー。
Avatar
rinsuki 10-Jun-17 01:35 PM
なるほど、認識はされているのですね...
13:35
代わりの書き方とかあるんでしょうか(あまり良くわかってない)
Avatar
mono 10-Jun-17 01:37 PM
??が常に遅いわけではなく、遅くなるケースがちょくちょくある、ということですよね?
Avatar
rinsuki 10-Jun-17 01:37 PM
そうですね
Avatar
mono 10-Jun-17 01:38 PM
もう少し細かく分離して変数で受けるだけでも速くなりそうな気がしました。 (edited)
Avatar
rinsuki 10-Jun-17 01:38 PM
なるほど
Avatar
tarunon 10-Jun-17 01:39 PM
これリテラルと混ざって書いてるのが原因の一端なので、Optionalが関わるところを隔離するだけで楽になるはず
Avatar
rinsuki 10-Jun-17 01:39 PM
var errorMessage:String = "" errorMessage = "エラーメッセージ:\n" errorMessage += errorMsg ?? "不明なエラー(iMast)" errorMessage += " (" errorMessage += String(httpNumber ?? -1) errorMessage += ")\n\nエラーメッセージに従っても解決しない場合は、アプリを再起動してみてください。"
のようにしたら早くなりました、ありがとうございます
Avatar
tarunon 10-Jun-17 01:40 PM
大体リテラルいくつかとオペレーターいくつかと並べると、組み合わせ爆発して遅くなります。これは??に限らず、有名なのだとBoolでorを並べたら大変なことになる、とか。
Avatar
rinsuki 10-Jun-17 01:40 PM
なるほど
13:40
無理に一行で書こうとせず、何行かに分けたほうがいいんですね
Avatar
tarunon 10-Jun-17 01:41 PM
人間が読むのが大変なのは機械も大変だったりします。
Avatar
rinsuki 10-Jun-17 01:41 PM
なるほど
Avatar
mono 10-Jun-17 01:43 PM
+=で連結ではなく、??絡むところだけ隔離して、()で文字列組み立てた方がベターに思いました。
13:44
バッククォート()と書いたのにバッククォートの記号消えちゃいました。
Avatar
tarunon 10-Jun-17 01:44 PM
\()←こいつ、中にちょっと式書くと音を上げるのであまり使ってないw
👀 2
Avatar
rinsuki 10-Jun-17 01:48 PM
うーん、\()どうも個人的に読みにくいんですよね
Avatar
mono 10-Jun-17 01:49 PM
文字列補間は他のモダンな言語でも大抵取り入れていて一般的に読みやすい気がしますが、それが嫌でも += ではなく、+でつなげるのが良いかなと思いました。
13:50
名前は適当ですが、こう分離して、 let errorMessage に +で連結して代入
let errorMsg2 = errorMsg ?? "不明なエラー(iMast)" let httpNumber2 = httpNumber ?? -1
Avatar
rinsuki 10-Jun-17 01:50 PM
なるほど
Avatar
tarunon 10-Jun-17 01:52 PM
多国語対応するつもりがなくても、Localizeファイル作っておいて、swiftgenなりR.swiftなりで、文字列を静的型で評価できるようにしておいた方が良い、というのもあった。
Avatar
mono 10-Jun-17 01:52 PM
ですね。
13:52
一覧されて見やすく管理しやすくもなりますね( ´・‿・`) (edited)
Avatar
tarunon 10-Jun-17 01:54 PM
%@や%iだと、Stringを作るための関数群として提供されるので非常に楽ですね。おすすめです。
Avatar
mono 10-Jun-17 01:54 PM
本当に多言語対応するつもりが無いのか、単に直近で無いだけのか、怪しいこともあるので、そういう意味でも、分離しておいた方が無難かなと思っています、分離も大した手間ではないので。 (edited)
Avatar
rinsuki 10-Jun-17 01:55 PM
なるほどー
Avatar
omochimetaru 10-Jun-17 01:56 PM
なんか
13:56
リテラルと足し算が絡んでると踏みやすい
13:57
感じがしている
13:57
配列リテラルに並べてjoinでくっつけるとかでも軽くなるかも
Avatar
mono 10-Jun-17 01:58 PM
Localizeファイル使うと、 いずれにせよ バッククォート() じゃなくて String(format: "", a, b) とかになりますね。 (数値絡んだりすると、 String.localizedStringWithFormat("", a, b) ) 今回の場合、これだけで速くなりそう。 (edited)
Avatar
rinsuki 10-Jun-17 02:02 PM
なるほど、ありがとうございます
Avatar
applideveloper 15-Jun-17 01:43 PM
‪アプリとWebが同じ機能をもっていて、万が一アプリで、ViewControllerが初期化できないとき開発ではfaitalError or nilでもいいが、本番ではnilで返して、遷移するコードでユーザーに遷移できません、その機能は現在使えませんでしたって伝えて戻るか、同じWebのページが表示できればバグ修正するまでWebを表示するのがいいんじゃないかと思うのですが、皆さんどうしてます?全部落とすとユーザーがもう一度アプリを開かない限りCrashlysticsにエラーが送られないので、障害検知できない気がするのですよ (edited)
Avatar
omochimetaru 16-Jun-17 03:44 AM
@applideveloper #ui-ux で返信しました
Avatar
omochimetaru 21-Jun-17 02:09 AM
Turns out that Tesla isn't a good fit for me after all. I'm interested to hear about interesting roles for a seasoned engineering leader!
Retweets
128
Likes
219
🚗 3
02:09
クリスラトナーがテスラ辞めそう
Avatar
tarunon 21-Jun-17 02:10 AM
マジかよw
Avatar
hiragram 21-Jun-17 02:10 AM
@clattner_llvm Let's all fix code signing together 🤗
Avatar
koher 21-Jun-17 02:10 AM
ええっw
Avatar
hiragram 21-Jun-17 02:11 AM
セグフォで落ちる自動運転車が生まれずに済んだのかもしれない。
Avatar
omochimetaru 21-Jun-17 02:12 AM
めちゃめちゃエラー出る自動運転車見たかったンゴ
Avatar
koher 21-Jun-17 02:14 AM
これでマイクロソフトとか行ったらおもしろそう。
Avatar
omochimetaru 21-Jun-17 02:14 AM
リプライちょこちょこありますね
Avatar
koher 21-Jun-17 02:15 AM
GoogleがSwift採用はないだろうけど、Microsoftならワンチャンあるかも?
Avatar
omochimetaru 21-Jun-17 02:16 AM
そして産まれるSwift.NET
Avatar
koher 21-Jun-17 02:16 AM
Avatar
hiragram 21-Jun-17 02:17 AM
AWSとか行ってサーバーサイドSwiftもっとやってほしい
Avatar
Biacco42 21-Jun-17 02:17 AM
そのうちもとの Swift がわざわざ Swift Native って呼ばれる流れか
Avatar
omochimetaru 21-Jun-17 02:17 AM
www
Avatar
koher 21-Jun-17 02:18 AM
Microsoftに行ってWIndows対応→Obj-CとSwiftみたいにC#と連携できるように→これまでのWindows資産を活かしてSwiftで開発できるように
02:19
ができればパイが広がりそう
Avatar
tarunon 21-Jun-17 02:19 AM
列強がドコドコリプライ送っててめっちゃおもろい
Avatar
omochimetaru 21-Jun-17 02:20 AM
わかる
Avatar
hiragram 21-Jun-17 02:33 AM
My resume is easy to find online. 7 years of Swift experience 👍
02:33
けっこうしっかり辞めそう
Avatar
omochimetaru 21-Jun-17 02:36 AM
Swift(スウィフト)は、アップルのiOSおよびmacOS、Linuxで利用出来るプログラミング言語。Worldwide Developers Conference (WWDC) 2014で発表された。
02:36
表に出てから3年しか経ってないから
Avatar
hiragram 21-Jun-17 02:36 AM
4年かけて作ってたんやなあ
Avatar
omochimetaru 21-Jun-17 02:36 AM
Appleは4年間開発してたんだ
Avatar
hiragram 21-Jun-17 02:37 AM
iOSいくつの頃よ
02:37
4とかか
Avatar
tarunon 21-Jun-17 02:37 AM
ARC無い頃から作ってたの?
Avatar
omochimetaru 21-Jun-17 02:37 AM
3.2 Wildcat 2010年4月3日 iPad(第1世代)
Avatar
koher 21-Jun-17 02:37 AM
I started work on the Swift Programming Language (wikipedia) in July of 2010. I implemented much of the basic language structure, with only a few people knowing of its existence. A few other (amazing) people started contributing in earnest late in 2011, and it became a major focus for the Apple Developer Tools group in July 2013.
Avatar
omochimetaru 21-Jun-17 02:37 AM
iOS3.2が2010年に出てる
Avatar
koher 21-Jun-17 02:37 AM
Avatar
Biacco42 21-Jun-17 02:38 AM
2010 ってまだ iOS そんな化石みたいなバージョンだったのか…
Avatar
omochimetaru 21-Jun-17 02:38 AM
ARCがiOS4からだから
Avatar
tarunon 21-Jun-17 02:38 AM
これswiftに合わせてObjCにARC作られた説、割と罷り通る
Avatar
omochimetaru 21-Jun-17 02:38 AM
MRCのときからやってたのか
02:38
あ〜〜〜
Avatar
Biacco42 21-Jun-17 02:38 AM
ありえますね
Avatar
omochimetaru 21-Jun-17 02:38 AM
LLVM側の改修が並行してObjCにおすそ分けされていたのか
Avatar
hiragram 21-Jun-17 02:38 AM
おお
02:39
納得感あるなたしかに
Avatar
norio_nomura 21-Jun-17 03:12 AM
"Automatic Reference Counting" という文字列が含まれる swift と clang の最初のコミット。 2011年4月15日 7:05:07 JST https://github.com/apple/swift/commit/3cce5623cb84cb839923ae4ac579ae50d18a0740 2011年6月16日 6:21:53 JST https://github.com/apple/swift-clang/commit/8246702d0cbecc3fd5748b58614ffed7ad9e04a5 (edited)
03:14
この時のSwiftのリポジトリにARCの実装が含まれているかどうかはよくわからないな。
03:17
clangにARCの実装が入った時のコミット 2011年6月16日 8:02:42 JST https://github.com/apple/swift-clang/commit/f85e193739c953358c865005855253af4f68a497
Language-design credit goes to a lot of people, but I particularly want to single out Blaine Garst and Patrick Beard for their contributions. Compiler implementation credit goes to Argyrios, Doug,...
Avatar
norio_nomura 21-Jun-17 03:28 AM
この時のSwiftのリポジトリにARCの実装が含まれているかどうかはよくわからないな。
その時点のSwift Language Referenceを見るとARCの実装とか影も形もなさげ。 https://github.com/apple/swift/blob/3cce5623cb84cb839923ae4ac579ae50d18a0740/docs/LangRef.html
swift - The Swift Programming Language
Avatar
omochimetaru 21-Jun-17 03:30 AM
typealias DataSearchFlags : oneof { None, Backward, Anchored }
03:30
enumもどきみたいなやつおる
Avatar
norio_nomura 21-Jun-17 03:41 AM
SwiftKickoff.rtf https://github.com/apple/swift/blob/3cce5623cb84cb839923ae4ac579ae50d18a0740/docs/SwiftKickoff.rtf
More Open Discussion
More concrete goals, plans, schedule through WWDC, etc.
How/when to engage with the rest of the company, when to go more public.
(edited)
swift - The Swift Programming Language
03:43
この時点ではApple社内でもSwiftの存在は知られていなかったぽいね。 (edited)
Avatar
omochimetaru 21-Jun-17 03:43 AM
ほお〜〜
Avatar
norio_nomura 21-Jun-17 03:44 AM
ARCがSwift発祥というのは無理がありそう。
Avatar
tarunon 21-Jun-17 03:44 AM
違ったか~
Avatar
omochimetaru 21-Jun-17 03:44 AM
あーなるほど。
Avatar
hiragram 21-Jun-17 04:49 AM
Tesla's autopilot software head quits in less than six months https://t.co/B8qvSrWDnS Via @Reuters #companynews
04:49
確定っぽい。
Avatar
omochimetaru 21-Jun-17 04:50 AM
Tesla Inc (TSLA.O) said the head of its autopilot software, Chris Lattner, left the company in less than six months since joining the electric carmaker.
04:50
head of って、リーダーだったのかな?
Avatar
hiragram 21-Jun-17 04:50 AM
VPじゃなかったけ
04:50
VP of Autopilotみたいなんだったきがする
Avatar
omochimetaru 21-Jun-17 04:51 AM
ほー
Avatar
hiragram 21-Jun-17 04:51 AM
Teslaは自動運転の取り組みを率いる新しい副社長を獲得した。Chris Lattnerだ。そのAppleからの離職は本日(米国時間10日)の早い時間に発表されたばかりだ。LattnerはAppleで11年働いた。その主な貢献はAppleの最新のプログラミング言語であるSwiftの開発である。Swiftは初心者がm..
Avatar
omochimetaru 26-Jun-17 04:13 AM
この新しいsubscriptめちゃくちゃ便利そう。 https://t.co/mN88tMyEoq
04:14
@omochimetaru @koher いや、それはそうだけど、dictionary[$0]が値の存在が保証されてるならdefaultは0じゃなくてNeverが妥当じゃない?って話
04:14
@tarunon [default: ] を指定するのは、値の存在が保証されてない場面では??
Avatar
tarunon 26-Jun-17 04:14 AM
Non Optionalにするための用法だから
04:14
+=するなら値保証されててもdefault要るっしょ
04:15
dict[key]! += 1 ってできたっけ?
Avatar
omochimetaru 26-Jun-17 04:16 AM
それじゃあ意味が違ってない?
04:16
というか、値保証されてるときはむしろdefault使っちゃだめでしょ
04:17
値が無いかもしれない => なかった時に使うデフォルト値を指定したい => 今回の dict[key, default: d] を使うべき 値があるはず => なかったときはクラッシュさせたい => dict[key]! を使うべき (edited)
Avatar
tarunon 26-Jun-17 04:18 AM
dict[key]!で+=使えるならそれはそう
Avatar
omochimetaru 26-Jun-17 04:18 AM
dict[key] += 1 ができるかどうかはわからないけど、 それができないからといって
Avatar
tarunon 26-Jun-17 04:18 AM
使った記憶がないから使えるか解っていない
Avatar
omochimetaru 26-Jun-17 04:18 AM
default: を使っちゃたら
04:18
値がない場合のエラーを握りつぶすパターンに書き換えていてよろしくないと思う。
Avatar
tarunon 26-Jun-17 04:18 AM
だから、0じゃなくてNeverいれようぜって話
Avatar
omochimetaru 26-Jun-17 04:19 AM
あ〜
04:19
dict[key, default: never()] += 1 こう?
Avatar
tarunon 26-Jun-17 04:19 AM
なおdict["key"]! += 1はSwift3時点で無理
04:19
そう
Avatar
omochimetaru 26-Jun-17 04:19 AM
@koher デフォルト値が絶対ある場合はundefined<T>とか使えば良さそう。
04:19
dict[key, default: undefined()] += 1
04:19
こう書くと良さそうですね、って言ってるのか。
Avatar
tarunon 26-Jun-17 04:20 AM
Optional, throwsで値が返ってくる系の問題は、返り値に対してvar structなパターンが使えないという点だな
04:20
それを克服できるので、しかし
04:20
デフォルト値に適当な数値を入れてしまうと
Avatar
omochimetaru 26-Jun-17 04:20 AM
「めちゃくちゃ便利そう」に対して、「undefined()で代用できるから不要」って反対してるのかとおもった。
Avatar
tarunon 26-Jun-17 04:20 AM
1. エラーが握りつぶされる 2. そこだけ読んで0が妥当かわからない
Avatar
omochimetaru 26-Jun-17 04:20 AM
他の応用方法を提示していたのか。誤読した。
Avatar
tarunon 26-Jun-17 04:20 AM
という問題を孕むので
04:21
最初から一貫してそう主張してるぞなw
Avatar
omochimetaru 26-Jun-17 04:21 AM
なるほど
04:21
いや、undefinedを「default: のところに指定する」っていうのがわかってなかった (edited)
Avatar
tarunon 26-Jun-17 04:21 AM
Neverがボトムになれba
04:21
まどろっこしい関数用意しなくて良くなるんだがな
Avatar
omochimetaru 26-Jun-17 04:23 AM
var x: [String: Int] = [:] x["aaa"] = 3 x["aaa"]! += 1 print(x["aaa"])
04:23
コンパイルできた。 出力
Optional(4)
Avatar
tarunon 26-Jun-17 04:23 AM
あれ、まじ?
Avatar
omochimetaru 26-Jun-17 04:23 AM
マジ
04:24
Version 8.3.3 (8E3004b)
04:24
これ不思議だね
Avatar
tarunon 26-Jun-17 04:24 AM
あーいけた
04:24
なんかミスってたっぽいな
Avatar
omochimetaru 26-Jun-17 04:24 AM
! 演算子はオペランドが左辺値の場合、左辺値のままにしてくれるのか。
04:25
そうすると話が巻き戻って dict[key]! += 1 で良いってことになるのか・・・?
Avatar
tarunon 26-Jun-17 04:25 AM
せやね
Avatar
omochimetaru 26-Jun-17 04:26 AM
てかそれだったら
04:26
dict[key] ?? defaultValue += 1
04:26
これがかけたら良かったような・・・?
04:26
これは厳しいか。 ?? の右側は別のストレージだもんな
Avatar
tarunon 26-Jun-17 04:26 AM
それどうやってdict[key]見つけんの
Avatar
omochimetaru 26-Jun-17 04:27 AM
一応できると思うんだよな
Avatar
tarunon 26-Jun-17 04:27 AM
まあそもそもDictionaryをガチャガチャ操作するのをやめろって話ではある
Avatar
omochimetaru 26-Jun-17 04:28 AM
readとwriteで別のストレージを見るアクセサになればいいから
04:29
なやましい
04:29
dict[key] ||= 3
rubyだとこういうのよく見る
(edited)
Avatar
tarunon 26-Jun-17 04:29 AM
dict[key] ?? dict[key2] ?? default += 2
04:29
これとかどうすんのっていう
Avatar
omochimetaru 26-Jun-17 04:32 AM
同じようにできると思う イメージ的には
func doubleQuestion( left: (read: ()->T?, write: (T)->Void), right: (read: ()->T, write: (T)->Void) ) -> (read: () -> T, write: (T) -> Void)
(edited)
04:33
実際には auto closure 的に read / write それぞれを取り出すことができないから無理だけど。
Avatar
tarunon 26-Jun-17 04:33 AM
結果の値を左辺の全ストレージにぶっこむってことね
Avatar
omochimetaru 26-Jun-17 04:34 AM
そだね、でもたしかに、2個めのdict[key2]にwriteするのかどうかとかわかりにくいな
Avatar
tarunon 26-Jun-17 04:34 AM
素直に理解できる構文ではなさそうだ
Avatar
koher 26-Jun-17 08:20 AM
完全に乗り遅れたけど、
Neverがボトムになれba まどろっこしい関数用意しなくて良くなるんだがな
これおもしろいですね。
08:20
dict[key, default: fatalError()] += 1
(edited)
08:20
ってできるのか。
Avatar
tarunon 26-Jun-17 08:21 AM
出来ますね、fatalErrorを使う優位性はメッセージ付きにできるところかな。
Avatar
koher 26-Jun-17 08:22 AM
Never がボトムタイプでない現状だと、
func never<T>(_ message: String = "") -> T { fatalError(message) }
みたいなのがいると。
Avatar
tarunon 26-Jun-17 08:23 AM
ですです
Avatar
koher 26-Jun-17 08:23 AM
Never がボトムタイプにならないのって誰も Proposal 書かないから?
08:23
なんか前スレッドありましたよね。どうなったんだろ。
08:24
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
08:26
An uninhabited type can be seen as a subtype of any other type ... This can be considered as a separate proposal.
Avatar
koher 26-Jun-17 08:35 AM
Avatar
tarunon 26-Jun-17 08:37 AM
はやいとこMLじゃないところに出てきてほしい、Thumbs upとか使いたい
Avatar
omochimetaru 26-Jun-17 08:41 AM
わかりすぎる
Avatar
tarunon 26-Jun-17 08:43 AM
議論しないと同意できないフローかなり辛い。Neverがボトムタイプになるべきなんて、議論する余地無いんじゃねっていうのが伸び悩むのが本当に良くない
Avatar
koher 26-Jun-17 08:47 AM
特に反対意見でなければ Proposal 作るフェーズに進んじゃってもいいのかも?でもスレ主的にはやりづらそうだけど。
Avatar
omochimetaru 26-Jun-17 08:48 AM
githubとかだと 👍 の絵文字が連打されたりするけどMLでそういうの無いしね
Avatar
koher 26-Jun-17 08:48 AM
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
08:49
今は "Socialize the idea" のフェーズだから
08:49
"Develop the proposal" に進んじゃうという手もある。
08:49
"Request a review" まで行けば Core Team も判断せざるを得ない。
08:51
ただ、これって元々の Proposal が Joe Groff だし、 Core Team が認識してないわけはないから
08:51
型システムに影響与えそうだし、 enum Never {} がボトムってどうなの?とか、他の enum Foo {} はどうなるの?とか、色々ややこしいから後回しにされてるのでは。
08:52
それとは別に↓には強く賛成です。
はやいとこMLじゃないところに出てきてほしい、Thumbs upとか使いたい
08:53
今も ML で
+1
みたいなリプライあるけどw
Avatar
omochimetaru 26-Jun-17 08:53 AM
あるけどMLでやると迷惑じゃないですか?
08:53
と思って、やらない人と、気にせずやる人にわかれそう
08:54
ていうか僕だったらスレッド一覧で見ていざ中身みたら +1 しか書いてなかったりして、そういうところもMLはだるい
Avatar
koher 26-Jun-17 08:55 AM
まあそもそも議論は多数決じゃないから +1 に本質的な意味はないのかもしれないけど、提案社的には賛同者がいることがわかればやりやすいかも。
Avatar
tarunon 26-Jun-17 08:56 AM
特に問題がないから議論が起きないのか、誰も興味が無いのかの判別がつかないのが辛い
Avatar
omochimetaru 26-Jun-17 08:56 AM
そうそう。
Avatar
koher 26-Jun-17 08:56 AM
ML からの移行は早くしてほしいし、 Core Team もやると言ってるし、でも急にはできないし、気長に待つしかなさそう・・・。
Avatar
moaible 27-Jun-17 03:00 AM
グローバル関数使うライブラリってSwifty的にNGですかね?
03:03
someFunc(AnyProtocol, parameter...) 的なのを考えてたんですが型で判別できるから、ありかどうかで迷ってる感じです
Avatar
t.ae 27-Jun-17 03:03 AM
Alamofireはdownloadとかあった気が
Avatar
moaible 27-Jun-17 03:04 AM
Alamofire - Elegant HTTP Networking in Swift
Avatar
t.ae 27-Jun-17 03:04 AM
型で分かるなら十分じゃないですか?
😀 1
Avatar
moaible 27-Jun-17 03:05 AM
ありがとうございます、ちょっと思いつめてたので助かりましたw
Avatar
omochimetaru 27-Jun-17 03:09 AM
というか
03:09
パッケージでネームスペースが切れているのでは?
03:10
さっきの downloadAlamofire.download ですよね 正式には
03:10
ちなみに min とかの組み込みも Swift.min です
Avatar
t.ae 27-Jun-17 03:10 AM
そういう意味だとグローバル関数とは?という話に
Avatar
moaible 27-Jun-17 03:10 AM
確かに、downloadで衝突してたらAlamofire.downloadで呼ぶしか無いのはあります
03:11
なんというか命名モラル的に行儀が良いのかって所がどうなのかなーと
Avatar
t.ae 27-Jun-17 03:11 AM
ネームスペースが切れててもdownloadでアクセスできるので 結局そこがどうなのかって話なわけですよね
Avatar
omochimetaru 27-Jun-17 03:12 AM
別に困らないし良いのでは
🙃 1
😂 1
Avatar
moaible 27-Jun-17 03:12 AM
気にしすぎだった説
Avatar
omochimetaru 27-Jun-17 03:14 AM
Javaだといざ衝突したときに com.omochimetaru.Alamofire.download とかなってシンドイけど Alamofire.download ならまあ別に平気だし、だいたいは引数の型でも区別可能だし。
03:14
もし複数のライブラリから download が出てきてごちゃごちゃしてきたときは
03:14
func alamofireDownload() { .. } とかを自作してラップするのが良いんじゃないでしょうか
03:14
本当は別名インポートの言語機能がほしいけど無いので。
Avatar
moaible 27-Jun-17 03:15 AM
import ... as ... 的なやつですか
Avatar
omochimetaru 27-Jun-17 03:15 AM
そうです
Avatar
t.ae 27-Jun-17 03:15 AM
それほしいですね
Avatar
omochimetaru 27-Jun-17 03:15 AM
ただ、グローバル関数って、ある意味シングルトンに対するメソッド呼び出しなので
03:15
シングルトンの問題と同じで、なんらかのレシーバにぶら下げて挙動を変えたいように
03:15
今後変更がかかりそうなら注意したほうが良さそう
Avatar
tarunon 27-Jun-17 03:16 AM
@tarunon なるほど、確かにそこも組み替えできるようにした方が可動域的な部分で良さそうです、もう少しいじって見ます😀 レビューありがとうございます、まさか誰か見てくれるとは思わずw
03:16
文脈はここだと思うんですが(具体的なアプローチを提案できて無くて申し訳なく...
Avatar
moaible 27-Jun-17 03:17 AM
いえいえ、レビュー嬉しかったです どういう風に直そうかなーって考えてました
Avatar
tarunon 27-Jun-17 03:17 AM
APIClient.init(URLSession)な実装にしておいて、シングルトンを避けて任意のAPIClientをinitするのが良いと考えていて
03:18
そもそもAPIClientのベースをfunc loadを持つprotocolとして定義しておけば、MockClientの実装をサクッと作れるよ、という感じでした
Avatar
moaible 27-Jun-17 03:21 AM
protocol APIRequestable { func load<R: Request>(request: R) -> R.Response }
って感じですかね?
Avatar
tarunon 27-Jun-17 03:22 AM
そうですね。僕が最近書いたコードは大体そんな感じになってます
Avatar
moaible 27-Jun-17 03:24 AM
なるほど、確かにそれぞれ用途ごとに準拠したものを用意すれば済みますね
03:25
自分が言われてからぼんやり考えてたのは
requests<R: Request>(adapter: RequestAdapter=DefaultRequestAdapter()) -> (request: R) -> R.Response
みたいにしようかで悩んでました
(edited)
03:25
結局どこに状態持たせるかって話になっちゃいますかね
Avatar
moaible 27-Jun-17 04:03 AM
↑ありがとうございます、とりあえずまた直してみます。 また何かあれば相談させてください🙂
Avatar
omochimetaru 28-Jun-17 01:25 AM
@norio_nomura > emscriptenちょっと試してみたけど「クロスコンパイルターゲットをどの様に用意するか?」な問題に移ってる様に見える。 どのように用意するか、とはどういうことですか?
01:26
emscriptenのコンパイルターゲットって宛先がJSかwasmかぐらいしか無いのかと思っていました
Avatar
norio_nomura 28-Jun-17 01:28 AM
エラーを見ると
warning: Linking two modules of different target triples: /Users/norio/.emscripten_cache/asmjs/libc.bc' is 'asmjs-unknown-emscripten' whereas 'hello_world.bc' is 'x86_64-apple-macosx10.9'
swiftcが生成したhello_world.bcのターゲットがx86_64-apple-macosx10.9になってるからダメだよ、となってる。
01:29
swiftctargetasmjs-unknown-emscripten.bcを生成できないとダメなんじゃないかな。
Avatar
omochimetaru 28-Jun-17 01:33 AM
Swift -> LLVMIR のコンパイル時点でemscripten環境をターゲットにするのか。そういうアーキテクチャなんですね
Avatar
norio_nomura 28-Jun-17 01:49 AM
あまりよくわかっていないのだけど、たぶんクロスコンパイル用のtoolchainを用意しなければいけないのと同じなんだと思ってる。 https://github.com/apple/swift-package-manager/pull/1098
General This adds experimental support for cross compilation or more precisely configurable destinations for binaries to SwiftPM. The basic idea is that you hand a JSON file in the format described...
Avatar
omochimetaru 28-Jun-17 02:00 AM
なるほど
02:01
emscriptenの時点で darwin-x64環境とかを抽象化するわけじゃないんですねえ
Avatar
norio_nomura 28-Jun-17 02:02 AM
emscriptenのissueには「asmjs-unknown-emscriptenWebAssembly(wasm32)とほぼ同じだよね?」って話してる人がいて、同じ人がSwiftをWebAssemblyへクロスコンパイルする話題をswift-devに投げてる。 https://lists.swift.org/pipermail/swift-dev/Week-of-Mon-20170626/004860.html (edited)
Avatar
omochimetaru 28-Jun-17 02:08 AM
おおアツい
02:08
For example, the Clang that ships with Xcode 9 includes support for wasm32 as a compilation target.
02:09
なるほど
03:04
ぼんやり考えていて、コールバック時の結果にErrorが入ってるときに、(T?, Error?)やResult<T>を使うのは辛いなと思っていたのが解決するなと。
Avatar
koher 30-Jun-17 03:07 AM
そうですね。僕は JS の Promise みたいに非同期処理とエラー処理をまとめて扱うような設計が嫌いで、非同期処理なら非同期処理、エラー処理ならエラー処理と責務を分解しておくべきだと考えて、エラー処理を含まない Promise ↓を作ってました。 https://github.com/koher/PromiseK/tree/dev-3.0
PromiseK - The Promise class designed as a Monad for Swift.
03:07
で、そうすると、この PromiseResult が対応してるなと思って、それらを throws, try (edited)
03:08
async, await に対応させれば、自由にまぜて使えるよなぁと考えたものです。
Avatar
tarunon 30-Jun-17 03:09 AM
今でもやろうと思えば、コールバックの値を() throws -> Tにすればイケると思うんですが
03:09
あまりやってるのは見ないですね
Avatar
koher 30-Jun-17 03:09 AM
ですねー。できるけど面倒ですしね。
03:10
せっかく安全なエラー処理機構を持っているのに、Promise にエラー処理を担当させちゃうと、 catch 忘れがおこっちゃうんですよねぇ。
Avatar
tarunon 30-Jun-17 03:10 AM
純正だとT?, Error?、Resultの民はResult<T>だ
Avatar
koher 30-Jun-17 03:11 AM
PromiseResult を一緒に使うとモナドパズルになっちゃうんですよねぇ。
03:11
Result<Promise<Result<Foo>>>Promise<Result<Foo>> にしたいとか。
Avatar
t.ae 30-Jun-17 03:11 AM
最近それやってて、windows版はasync+throwでできて良かった
Avatar
tarunon 30-Jun-17 03:12 AM
C#ですか?
Avatar
t.ae 30-Jun-17 03:12 AM
はい。
Avatar
omochimetaru 30-Jun-17 03:12 AM
C#はasync-awaitは明示的だけどthrowが・・・
Avatar
koher 30-Jun-17 03:12 AM
Array<Promise<Result<Foo>>>Primise<Result<Array<Foo>>> にしたいとか。
Avatar
t.ae 30-Jun-17 03:13 AM
その移し替えはめんどくさそうだ
Avatar
tarunon 30-Jun-17 03:13 AM
その辺のメリットも明記したら伝わりやすいのかな、というのと
Avatar
t.ae 30-Jun-17 03:14 AM
jsだとPromise.allとかあったけどエラーハンドリングが分離してるから純粋にはできないのか。
Avatar
koher 30-Jun-17 03:14 AM
そうですねぇ。あまり詳細まで書くと長くなって読まれないんじゃないかという心配もあって、議論の中で説明できればいいかなと。英語で議論についていけるのかあやしいですが。
03:16
ちなみに、 PromiseK 3.0 では
let a: Promise<Int> = ... let b: Promise<() throws -> Int> = a.map { try foo($0) }
みたいに、 map 等の中で throw される場合は戻り値の型パラメータを () throws -> Foo に変換する API を考えてます。
03:17
async, await ができれば無用の長物ですが。
Avatar
tarunon 30-Jun-17 03:18 AM
ambiguous出そうw
Avatar
koher 30-Jun-17 03:19 AM
あと、おもしろいかなと思って、
typealias Promise<Value> = (@escaping (Value) -> ()) -> ()
とする Promisure (= Promise + Closure) というライブラリも作ってましたw
03:19
// Wrapping let a: Promise<Int> = { $0(3) } // like `Promise.resolve(3)` in JS // Promisifying a callback let b: Promise<Int> = promise { resolve in // Gets 5 after 1.0 seconds DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { resolve({ $0(5) }) } } // Operators let sum: Promise<Int> = a >>- { a in b >>- { b in { $0(a + b) } } } // flatMap let square: Promise<Int> = { $0 * $0 } <^> a // map let vector: Promise<Vector2> = curry(Vector2.init) <^> { $0(2.0) } <*> { $0(3.0) } // apply
Avatar
omochimetaru 30-Jun-17 03:19 AM
Promiseの型パラに関数型入っとる・・・
Avatar
koher 30-Jun-17 03:20 AM
関数型は non-nominal なので extension が生やせないので、メソッド代わりに全部演算子になってます。
03:24
@tarunon Rx の Observable にエラーが組み込まれてるのも僕は好みじゃないんですが、どうにかならないものでしょうか。
Avatar
omochimetaru 30-Jun-17 03:24 AM
あ〜 > extension
Avatar
tarunon 30-Jun-17 03:25 AM
僕も全く同じ気持ちで
03:26
あーでも
03:26
ObservableはErrorは停止なので、色々厳しそう
Avatar
t.ae 30-Jun-17 03:27 AM
Error排除できるタイプのもあるしそういう方向で対応しようってことになってるんじゃないですか?
Avatar
tarunon 30-Jun-17 03:27 AM
SharedSequenceですね
Avatar
koher 30-Jun-17 03:28 AM
その場合って、 failable な型が重複して似た仕組みを持つことになるけど、それは仕方ないか・・・。
Avatar
tarunon 30-Jun-17 03:28 AM
Observableになんとか、throws-rethrowsの機構を組み込みたい
Avatar
koher 30-Jun-17 03:29 AM
やっぱ、 throws, try みたいな特殊構文用意するよりも、モナドに対して do 記法用意するとかの方が汎用性はありますよねぇ。
03:29
入れ子モナドのパズルを解決するいい方法が必要だけど・・・。
Avatar
tarunon 30-Jun-17 03:30 AM
さっきのPromiseの例は上手い解決かもしれなくって
03:30
ちょっと後で考えてみよう
Avatar
koher 30-Jun-17 03:30 AM
あれって、 ResultPromise なら Promise が外側にいてほしいとか、モナド感での precedence みたいなものが考えられる気がして、
03:31
その順に全部いいように組み替えてね関数が一つあればうまくいきそうな気も?
Avatar
tarunon 30-Jun-17 03:31 AM
物凄い筋肉質なオーバーロードした関数が存在しそう
Avatar
omochimetaru 30-Jun-17 03:31 AM
筋肉質なオーバーロードw
Avatar
koher 30-Jun-17 03:32 AM
いや、オーバーロードじゃなくて
03:32
Monad 型に対して演算子みたいな precedence を指定できて
03:32
sort 関数みたいに、それを使って入れ子を関数が解決する。
Avatar
tarunon 30-Jun-17 03:32 AM
高階型ないからオーバーロード必須ですよ多分
Avatar
koher 30-Jun-17 03:33 AM
ああ、高階型あり前提です。
Avatar
omochimetaru 30-Jun-17 03:34 AM
型同士の合成規則を2つの型の優先度の2項関係を表す型の集合で記述して
03:34
型解決の枠組みで静的に決定
03:34
みたいな・・・
Avatar
koher 30-Jun-17 03:35 AM
で、後はネストモナドまとめてアンラップもできれば。↓みたいな?
let a: Result<Promise<Int>> = ... let b: Promise<Result<Int>> = magic(a) do { let c: Int <-- b // 多段アンラップ let d: Result<Int> <- b // 一段アンラップ }
03:37
そしたらモナドのネストも恐れる必要がない(組み換え問題とアンラップ問題を同時に解決できる)気がするし、いちいち try とかキーワード足さなくても自作モナドを組み込みモナドと同じように便利に使える。
Avatar
tarunon 30-Jun-17 03:41 AM
うーん
03:42
殊、asyncとthrowsに関しては汎用性云々というより (edited)
03:42
あまりにも出現頻度が多すぎるので言語仕様でサポートしたほうが平和なのでは?という気がしている
Avatar
koher 30-Jun-17 03:43 AM
そうですねぇ。特殊構文はそれはそれで見やすいんですよね。
03:43
PromiseK では thenmapflatMap になってるんですけど、ネストしてくると読みづらいんですよねぇ・・・。
Avatar
tarunon 30-Jun-17 03:44 AM
then、Swiftコンパイラには荷が重いのでmap/flatMapにしたほうが良いよ派の人間です
Avatar
omochimetaru 30-Jun-17 03:44 AM
人間にも重いと思う派
Avatar
tarunon 30-Jun-17 03:44 AM
コンパイラが理解できないのは人間にも理解できないよ
03:45
大体の場合ね
Avatar
omochimetaru 30-Jun-17 03:45 AM
じゃあ同じ意見だった
Avatar
koher 30-Jun-17 03:45 AM
ただ、 Swift は Result を作らなかったから thorws, try を別の型でラップしたい場合に Promise<() throws -> Int> とかなるのはちょっとつらいですよね。
Avatar
tarunon 30-Jun-17 03:46 AM
Promiseがasyncに昇格されれば辛さは消えますよ
Avatar
koher 30-Jun-17 03:46 AM
はい、それはそうです。けど、 Observable とかでやろうとしたらできないですよね?
Avatar
tarunon 30-Jun-17 03:46 AM
そうなんですよねぇ
Avatar
koher 30-Jun-17 03:46 AM
結局別のエラー処理機構を導入せざるを得ない。
Avatar
omochimetaru 30-Jun-17 03:46 AM
ですね
Avatar
tarunon 30-Jun-17 03:47 AM
throws () -> Tにしなきゃいけないのがしんどいので
Avatar
omochimetaru 30-Jun-17 03:47 AM
async / awaitが言語に入ったときに
Avatar
tarunon 30-Jun-17 03:47 AM
throws Tがあれば
Avatar
omochimetaru 30-Jun-17 03:47 AM
言語サポートがあるけど非同期としては貧弱なPromiseと
03:47
言語サポートが無いけど非同期機構としてはリッチなObservableが
03:47
存在する環境になって
03:47
甲乙つけがたくなりそうでそこはちょっとナーバスになっている
Avatar
tarunon 30-Jun-17 03:48 AM
Observable相当のものが言語機能に降りてこないかな~というのを考えてるけど
Avatar
omochimetaru 30-Jun-17 03:48 AM
それはなあ・・・
Avatar
tarunon 30-Jun-17 03:48 AM
これは前おもちくんと話したな
Avatar
omochimetaru 30-Jun-17 03:48 AM
細かい設計に柔軟性がありすぎてコンセンサスも取れなさそう。
03:48
RACだと Signal / SignalProducer で Hot / Cold を型付けしたりしてるし
Avatar
koher 30-Jun-17 03:49 AM
シンプルな Promise であれば議論の余地がほぼなさそうだけど、 Observable レベルになると枯れてなくて言語機能にするにはつらそう・・・
Avatar
omochimetaru 30-Jun-17 03:49 AM
そうなんですよねえ
Avatar
koher 30-Jun-17 03:50 AM
だから、ライブラリでも組み込み構文に近い便利さを享受できる言語仕様になってればいいなぁと思うんですけどねぇ。
Avatar
tarunon 30-Jun-17 03:50 AM
治安は悪化しそう
Avatar
koher 30-Jun-17 03:50 AM
それはそうですねw
03:51
文化が断裂してお互いに理解できないコードの世界が出来上がりそうw
03:51
まあ、でも Rx はすでにそうなってるような気も。
Avatar
omochimetaru 30-Jun-17 03:53 AM
Rxはそうなんですけど
03:53
言語をまたいだ世界だから
03:54
まあいっかって気持ちになる
03:54
(RxSwiftの呪文を覚えるとJavaでも使える
Avatar
tarunon 30-Jun-17 03:54 AM
まだ関数呼び出しの範疇に収まってるから平気だけど
03:54
構文拡張とかやっていったら人死にが出る
03:54
オレオレoperatorですら結構辛いのに
Avatar
omochimetaru 30-Jun-17 03:54 AM
ですね
Avatar
koher 30-Jun-17 03:55 AM
構文拡張というか、汎用的に使える構文って意味ですね。
Avatar
tarunon 30-Jun-17 03:55 AM
Javaのアノテーションもしんどい
Avatar
moaible 30-Jun-17 03:55 AM
RxSwiftのSwift2の頃のオペレータは結構好きでした
03:55
>-
Avatar
omochimetaru 30-Jun-17 03:56 AM
マジすかあ
Avatar
tarunon 30-Jun-17 03:57 AM
隣の同僚がオレオレオペレーターてんこ盛りプロジェクト引き継いでブチ切れながら消していってて、まぁそうっすね…みたいな感じ
Avatar
omochimetaru 30-Jun-17 03:57 AM
最初ひょえ〜っとなって、やっていくうちに、あれ、これメソッドでいいのでは?となって、Swift側の制約でできないからやってるとわかって、Swift3でメソッドになって気持ちが落ち着いた (edited)
Avatar
moaible 30-Jun-17 03:57 AM
他のライブラリ含めてオレオレoperator廃止されていってるのを見て、これあかんやつなのかってなったのは記憶にあります
Avatar
omochimetaru 30-Jun-17 03:58 AM
たしかジェネリック型に対するextensionメソッドがまだショボくって
03:58
でも演算子ならいけるみたいな
03:58
状態だったんですよね。
Avatar
tarunon 30-Jun-17 03:58 AM
あったあった
03:58
オレオレオペレータ廃止の流れは
Avatar
koher 30-Jun-17 03:58 AM
今でも、 non-nominal の extension 書けないから
Avatar
tarunon 30-Jun-17 03:58 AM
そもそも言語機能としてオレオレオペレータの何かが削られたからっていうのが
Avatar
omochimetaru 30-Jun-17 03:58 AM
Swift3の仕様強化でだいぶオペレータが排除できた
Avatar
koher 30-Jun-17 03:58 AM
オペレータならできる状態が終わってない・・・
Avatar
tarunon 30-Jun-17 03:58 AM
大きかった気がする
03:58
non-nominalはありますね
Avatar
koher 30-Jun-17 03:59 AM
例の => も。
Avatar
omochimetaru 30-Jun-17 03:59 AM
そうですねえ そして関数型が non-nominal である影響がでかい。
03:59
=> が演算子にしかできないのも Any型がnon-nominalだからだっけ (edited)
Avatar
koher 30-Jun-17 03:59 AM
まあ、 => レベルだと演算子の方が可読性高そうだけど。
03:59
Any でもダメで、任意の型パラじゃないといけないから辛い・・・
Avatar
omochimetaru 30-Jun-17 04:00 AM
ん?とは?
04:00
もしAnyに対するextension methodで書けたとして、それでも 拾えないパターンってどういうのがあるんでしょうか (edited)
Avatar
koher 30-Jun-17 04:00 AM
extension Any { func `let`<T>(_ f: (Any) -> (T)) -> T { ... } }
04:00
だったら、クロージャの引数が Any になっちゃって
04:01
ダウンキャストしないといけなくて面倒。
Avatar
omochimetaru 30-Jun-17 04:01 AM
そこは Self では
Avatar
koher 30-Jun-17 04:01 AM
そこ Self にする extension ってできるんだっけ?
Avatar
omochimetaru 30-Jun-17 04:01 AM
わからないw
Avatar
tarunon 30-Jun-17 04:01 AM
えーっと
04:01
Anyはprotocolなんでいけます
04:02
are
Avatar
koher 30-Jun-17 04:02 AM
↓演算子実装
public func =><T, U>(lhs: T, rhs: (T) throws -> U) rethrows -> U { return try rhs(lhs) }
Avatar
omochimetaru 30-Jun-17 04:03 AM
classだとできないな
class Animal {} class Cat : Animal { func nya() { print("nyaa") } } extension Animal { func exec(f: (Self) -> Void) { f(self) } } let cat = Cat() cat.exec { $0.nya() } error: TempGround.playground:11:12: error: value of type 'Animal' has no member 'nya' cat.exec { $0.nya() } ^~ ~~~
Avatar
tarunon 30-Jun-17 04:03 AM
classはですね
04:03
extension SomeProtocol where Self: SomeClass {} (edited)
04:04
これでSelfが使えるようになる
04:04
Anyがextensionできるなら、
04:04
extension Any where Self: SomeClass {}
04:04
これでよさ
Avatar
koher 30-Jun-17 04:05 AM
お、できた
04:06
protocol Anything {} extension Anything { func `let`<T>(_ f: (Self) throws -> T) rethrows -> T { return try f(self) } } extension Double: Anything {} (42.0).`let` { $0 + 1.0 / $0 }
Avatar
omochimetaru 30-Jun-17 04:06 AM
protocol Proto {} class Cat : Proto { func nya() { print("nyaa") } } extension Proto { func exec2(f: (Self) -> Void) { f(self) } } let cat = Cat() cat.exec2 { $0.nya() }
04:06
できた
04:06
@tarunon whereなしでかけた
Avatar
tarunon 30-Jun-17 04:06 AM
いやいや
04:07
それだとCatのメソッド使えなくなるぞ
Avatar
omochimetaru 30-Jun-17 04:07 AM
exec2のなかで nya() が呼べたよ。
Avatar
tarunon 30-Jun-17 04:07 AM
exec2自体の実装の中でnya()呼べないという意味
Avatar
omochimetaru 30-Jun-17 04:07 AM
今の => の議論からするとそれは問題ないのでは
Avatar
tarunon 30-Jun-17 04:08 AM
用途をletに限るならまあそう
Avatar
omochimetaru 30-Jun-17 04:08 AM
=> の実装をオペレータからメソッドにできるかどうかだけを今考えていて
Avatar
koher 30-Jun-17 04:09 AM
これで問題なのは Any が nominal でないってことだけなわけだ。
Avatar
omochimetaru 30-Jun-17 04:09 AM
現状は Any に対する extensionが書けないからできない、
04:10
もし書けるのであれば Selff に渡す形で実装はできる。
04:10
@koher 現状でも
Avatar
koher 30-Jun-17 04:10 AM
うん
Avatar
omochimetaru 30-Jun-17 04:10 AM
Any じゃなくてLettable という protocol のメソッドとして作って
04:10
.let を使いたい型については extension Cat : Lettable {}
04:10
と、1つずつユーザーが書いていけばできそう。
Avatar
koher 30-Jun-17 04:10 AM
面倒すぎでしょw
Avatar
omochimetaru 30-Jun-17 04:10 AM
はい・・・
😕 1
Avatar
koher 30-Jun-17 04:11 AM
そして可読性の観点でも => の方がいいと思う。
Avatar
omochimetaru 30-Jun-17 04:11 AM
let束縛感がありますね
Avatar
tarunon 30-Jun-17 04:11 AM
可読性はちょっと疑問があって
04:11
広く知られてればまあそれはそう
04:12
1 + 1 と 1.add(1) だと俄然前者のほうが良い
04:12
f <$> [1] と [1].map(f) はさてどうだろう、という (edited)
04:12
広く知られればいいけど。
Avatar
koher 30-Jun-17 04:13 AM
<$> は順番が逆転しちゃう問題もありますしねぇ・・・
04:13
さっきの Promise のチェーンは
Avatar
tarunon 30-Jun-17 04:13 AM
あー逆だったか
Avatar
koher 30-Jun-17 04:13 AM
promise.flatMap { ... }.flatMap { ... }.flatMap { ... }
04:13
よりも
Avatar
omochimetaru 30-Jun-17 04:14 AM
なんじゃこれって思ったときに調べにくいという問題はあるね
Avatar
koher 30-Jun-17 04:14 AM
primise >>- { ... } >>- { ... } >>- { ... }
04:14
のようが見やすい
04:14
ググラビリティ低い問題はある。
04:14
記号検索させてほしい。
04:14
記号検索エンジンにニーズある気がする。
Avatar
omochimetaru 30-Jun-17 04:14 AM
あとはxcodeがもっとキビキビ動けば Cmd + Click できるんだが
04:15
だいたい indexing... 😴 だからな
😂 1
04:15
定義にも飛べないしググることもできなくておわり
04:16
http://blog.fkoji.com/2017/03052055.html Google 検索ではすでに記号1文字の検索はできるようになっていましたが、新たにプログラミングでよく使われる「===」や「+=」といった、複数の記号が連なる演算子などの特殊記号の検索ができるようになったそうです。
Google 検索ではすでに記号1文字の検索はできるようになっていましたが、新たにプログラミングでよく使われる「===」や「+=」といった、複数の記号が連なる演算子などの特殊記号の検索ができるようにな…
Avatar
koher 30-Jun-17 04:16 AM
=> は標準ライブラリに入れてほしい・・・。
04:16
え、できるの?
Avatar
omochimetaru 30-Jun-17 04:16 AM
最近グーグルが強化されたらしいけどさっきpythonの r''' 出せなかったし嘘だと思う
Avatar
t.ae 30-Jun-17 04:16 AM
正規表現ですか?
Avatar
omochimetaru 30-Jun-17 04:17 AM
r''' は正規表現じゃなくて生マルチライン文字列
Avatar
t.ae 30-Jun-17 04:17 AM
知らないのだ
Avatar
omochimetaru 30-Jun-17 04:17 AM
@t.ae さっきこれを解読してた https://github.com/apple/swift/blob/master/utils/gyb.py#L67-L82
swift - The Swift Programming Language
Avatar
t.ae 30-Jun-17 04:19 AM
ああ、rってregexのことかとおもってたらrawなのか
04:19
正規表現でしか使ったことなかったから完全に勘違いしてた
Avatar
omochimetaru 30-Jun-17 04:19 AM
pythonは正規表現リテラルは存在しない
Avatar
koher 30-Jun-17 04:20 AM
うーん、なんとなく動いてそう?
Swift >>-
で検索したら、一つ目は https://www.apple.com/jp/swift/ だけど、二つ目は typelift/Operadics で、三つ目は thoughtbot/Runes だった。
04:20
以前よりはずっとマシな気が。
Avatar
koher 30-Jun-17 04:21 AM
<$> はないよ
Avatar
tarunon 30-Jun-17 04:21 AM
できない
Avatar
koher 30-Jun-17 04:21 AM
<^> にマッピングされてる。
Avatar
omochimetaru 30-Jun-17 04:21 AM
ああそっか。 でも <^> も駄目っぽいですよ
Avatar
koher 30-Jun-17 04:21 AM
>>= は重複してるから >>- に、 <$> は言語仕様上の制約で <^> になってる。
Avatar
t.ae 30-Jun-17 04:21 AM
haskell <$>でもいまいちヒットしてない感
Avatar
omochimetaru 30-Jun-17 04:22 AM
What does <$> mean in Haskell? - Stack Overflow https://stackoverflow.com/questions/.../what-does-mean-in-haskell このページを訳す 2016/05/17 - Google is not the best search engine for Haskell. Try Hoogle or Hayoo, both will point you right away to this ...
04:22
最初に出た!
Avatar
koher 30-Jun-17 04:22 AM
While reading a piece of Haskell code I came upon this: <$>. What does it mean in Haskell? After some google searches I remain in the dark.
Avatar
omochimetaru 30-Jun-17 04:22 AM
いけてそう
Avatar
koher 30-Jun-17 04:22 AM
公式じゃないけど
04:22
まあないよりマシそう。
04:23
swift <^> は出ないなぁ。
Avatar
t.ae 30-Jun-17 04:23 AM
要約のほうがぜんぜんでないだけかな
Avatar
koher 30-Jun-17 04:23 AM
普通の Google 検索と比べると、 10% くらいの精度で一応動いてそう・・・。
😅 1
Avatar
tarunon 30-Jun-17 04:24 AM
普通のGoogle検索もSEO頑張る人間に潰されててなんか辛い。最近動きありましたっけ。
Avatar
t.ae 30-Jun-17 04:24 AM
|>は出た
Avatar
koher 30-Jun-17 04:25 AM
SEO は辛いですが、 Google ないよりはるかにいいですからねぇ。
04:26
この前、 Google を初めて知ったときのことを思い出してたんですが、試しに何かの名称を検索してみたら公式サイトが一番上に出てきて感動したことを覚えてるんですよ。 (edited)
04:27
つまり、 Google 以前の検索エンジンは、何かで検索してトップに公式サイトが出ることがなかったってことなんです。もうそんな世界で生きていけない・・・。
Avatar
tarunon 30-Jun-17 06:53 AM
associatedvalueを持ったenumの抽象化を書きたくて、
06:54
結局具体型を作らざるを得ないのはわかったけど名前が困る
06:54
2つならEither<L, R>でいいけど3つ以上(個数ごとに作る必要はある)の名前は何にするべきなのか
Avatar
omochimetaru 30-Jun-17 06:54 AM
Either2<T1, T2> Either3<T1, T2, T3>
Avatar
tarunon 30-Jun-17 06:55 AM
それ割とやるんだけど
Avatar
koher 30-Jun-17 06:55 AM
Either<T, Either<U, V>>
Avatar
tarunon 30-Jun-17 06:55 AM
他の言語とか見てもEither型はL,Rしかない
Avatar
t.ae 30-Jun-17 06:55 AM
そもeitherという語から二者択一感を感じる
Avatar
omochimetaru 30-Jun-17 06:56 AM
じゃあN者択一型はなんて名前になってるん?
Avatar
koher 30-Jun-17 06:56 AM
either a, b or c って言えないんだっけ?
Avatar
tarunon 30-Jun-17 06:56 AM
@koher ネストさせるとツリー構造に対して無限の分岐を埋めなきゃいけなくなるんでちょっと
Avatar
koher 30-Jun-17 06:57 AM
3者以上からの選択1の用法では, ⦅まれ⦆に3者以上からの択一の際にeitherを用いることがあるが, any (one)の方が普通
🙃 1
Avatar
tarunon 30-Jun-17 06:57 AM
Whichなのかなーとか
06:57
思ったけど型名であると考えるとEither型の方が認知は絶対高くて、しかしEither3,4,5のような用法は
06:58
ググった感じそんなになさそう
Avatar
koher 30-Jun-17 06:58 AM
多分 Tagged Union で Untagged 的な振る舞いをさせるのがあまりよくないような・・・
Avatar
tarunon 30-Jun-17 06:59 AM
ほしいのはenumの抽象化
06:59
ケースが幾つあって型がそれぞれあってswitchで保証される
Avatar
omochimetaru 30-Jun-17 06:59 AM
僕は C++ で Tagged Union が使いたくてシコシコ実装中
Avatar
moaible 30-Jun-17 07:00 AM
気になって見ててもAnyで使ってる人が多そうな雰囲気 > 複数形 https://english.stackexchange.com/questions/129288/words-similar-to-either-and-neither-for-3-items
Given two options, we can use 'either and 'neither' to show no preference. Do you want to watch A or B Neither, I don't like either. The only option I can see for more than two options is:...
Avatar
koher 30-Jun-17 07:00 AM
AnyOf とか OneOf とか?
Avatar
tarunon 30-Jun-17 07:00 AM
public enum Either2<A, B> { case a(A) case b(B) } public protocol Either2Convertible { associatedtype CaseA associatedtype CaseB var asEither: Either2<CaseA, CaseB> { get } } extension Either2: Either2Convertible { public var asEither: Either2 { return self } }
07:01
↑こういうのを、あと3,4,5くらいまで作っておくとして
07:01
Either3…ん?となった
Avatar
koher 30-Jun-17 07:02 AM
enum の抽象化ってことは、 Either2<Int, String>Either2<String, Int> は区別したいってことですよね?
Avatar
tarunon 30-Jun-17 07:02 AM
それはしますね
07:04
enumの抽象化、いい加減方方で使いすぎてるんで、マイクロフレームワークで作りおきしておこうというモチベになった
Avatar
koher 30-Jun-17 07:04 AM
うーん、このレベルで抽象化したいことがあまりなさそうで、それをしたくなったときは諦めて複数書くとか?
07:04
使いまくってるのか・・・
Avatar
tarunon 30-Jun-17 07:05 AM
任意のenumを引数に取る関数、が必要になることが多くて
07:05
そのたびに作ってますね
07:05
ん?
Avatar
koher 30-Jun-17 07:05 AM
たとえばどんな関数ですか?
Avatar
tarunon 30-Jun-17 07:05 AM
enum Enum2, protocol Enum2Convertible
07:05
これでいいんじゃないかな
07:06
直近で言うと
Avatar
koher 30-Jun-17 07:06 AM
Enum2, Enum2Convertible は良さそう
Avatar
tarunon 30-Jun-17 07:06 AM
RxDataSourcesのdataSource作るのが面倒くさいので
07:07
型を食わせてprotocol orientedに半自動生成させていて
Avatar
koher 30-Jun-17 07:07 AM
Enum1Enum0 もいらないですか? BoxNever
Avatar
tarunon 30-Jun-17 07:07 AM
Cell型が複数の時に必要になる
07:07
作っちゃおう
07:08
個数ごとにコードを書く必要はあるんですが、1~5個作っておけば5個まではもう、DataSourcesを生成するコードを書かなくて良くなるんで
Avatar
koher 30-Jun-17 07:08 AM
Enum3 とかだと CaseA より Case1 とかの方がよさそう
Avatar
tarunon 30-Jun-17 07:08 AM
ですね
Avatar
koher 30-Jun-17 07:09 AM
0 から始めるか少し迷うけど 1 からかなぁ。
07:09
でもタプルは 0 からか
07:09
それなら 0 からかなぁ
Avatar
tarunon 30-Jun-17 07:09 AM
Tuple 0はVoidなんで
07:09
Enum 0はNever
Avatar
koher 30-Jun-17 07:09 AM
あ、ではなくて
Avatar
tarunon 30-Jun-17 07:09 AM
まあそこはそう、美しいと思う
Avatar
koher 30-Jun-17 07:09 AM
enum Enum2<T0, T1> { case Case0(T0) case Case1(T1) }
Avatar
tarunon 30-Jun-17 07:10 AM
あw
07:10
そういうことか
Avatar
koher 30-Jun-17 07:10 AM
にするかです。
Avatar
tarunon 30-Jun-17 07:10 AM
まあ0でいいんじゃないですかね
Avatar
koher 30-Jun-17 07:10 AM
そのほうが一貫性はありますよね
07:11
パッケージ名は EnumN とか?
Avatar
tarunon 30-Jun-17 07:11 AM
EnumConvertibleかなんかにしようかと思っていた
07:11
Convertible大好き人間
Avatar
koher 30-Jun-17 07:12 AM
なるほど
Avatar
moaible 30-Jun-17 07:12 AM
ここで言うところのenum CellModelがさらにEnum2的な型で抽象化されるイメージです? https://twitter.com/tarunon/status/854349403322175489
@moaible つまり、enum CellModel { case cellType1, .... }と enum SectionModel { case section1([CellModel]), ... }
Avatar
koher 30-Jun-17 07:12 AM
あとはリポジトリ名を UpperCamelCase するか小文字ハイフンつなぎにするかも迷いどころw
Avatar
tarunon 30-Jun-17 07:12 AM
あーですね
07:14
UpperCamelCase vs chain-caseは宗教戦争っぽい
07:14
どっちがどうなんだ
Avatar
t.ae 30-Jun-17 07:14 AM
enum絡むライブラリ作ったら名前これにしようと思ってた http://ejje.weblio.jp/content/Houyhnhnm
Avatar
koher 30-Jun-17 07:14 AM
GitHub の主流はハイフンつなぎだけど Swift のライブラリは UpperCamelCase が多かったけど
07:15
Swift is a general-purpose programming language built using a modern approach to safety, performance, and software design patterns.
Avatar
omochimetaru 30-Jun-17 07:16 AM
Houyhnhnm 音節Hou・yhn・hnm 発音記号/hwínəm|húːɪ‐/ 名詞可算名詞 フーイナム 《Swift 作 Gulliver's Travels (ガリバー旅行記)の中の人間的な理性が徹底している馬; 人間の形をした Yahooを支配する》. [馬の鳴き声からのSwiftの造語]
Avatar
koher 30-Jun-17 07:16 AM
これのサンプルが https://github.com/apple/example-package-fisheryates なのを見て以来、やがてハイフン区切りの波に抗えなくなるんじゃないかという気がして、最近僕はハイフンばっかです。
example-package-fisheryates - Example package for use with the Swift Package Manager
Avatar
omochimetaru 30-Jun-17 07:16 AM
????
07:16
Swiftとは クイック再生 プレーヤー再生 ピン留め 単語を追加 主な意味 スウィフト 《1667‐1745; 英国の文人; Gulliver's Travels の作者》 音節 swift 発音記号・読み方 /swíft(米国英語)/
Avatar
t.ae 30-Jun-17 07:16 AM
ガリヴァー旅行記はスウィフト作
Avatar
tarunon 30-Jun-17 07:16 AM
なるほどー
Avatar
omochimetaru 30-Jun-17 07:16 AM
Swiftって名前の人いたのか
Avatar
tarunon 30-Jun-17 07:17 AM
ガリバー旅行記から名前取るのオシャンティー過ぎて僕にはちょっと
Avatar
koher 30-Jun-17 07:17 AM
@omochimetaru テイラー・スウィフトもいるでしょ?
Avatar
omochimetaru 30-Jun-17 07:17 AM
swift-package-manager - The Package Manager for the Swift Programming Language
07:17
SPMそれじたいもハイフンですね
Avatar
koher 30-Jun-17 07:17 AM
うん
07:17
Apple がそのスタイルとってる以上、やがて抗えなくなると思うんよね
07:18
パッケージ名は UpperCamel 、リポジトリ名はハイフンかなぁと。でも、ディレクトリは UpperCamel にしとかないと、 swift package init したときに面倒😅
Avatar
t.ae 30-Jun-17 07:19 AM
ローカルではUpperCamelで作ってリポジトリはハイフンつなぎが一番楽そう
Avatar
moaible 30-Jun-17 07:19 AM
コマンド引数で渡せたら楽なのにとは思いますね
Avatar
koher 30-Jun-17 07:20 AM
ですねー。渡せないですよね?何かあるのかなと思ってたんですが見つけられず。
Avatar
moaible 30-Jun-17 07:20 AM
$ swift package init --help OVERVIEW: Initialize a new package OPTIONS: --type empty|library|executable|system-module
Avatar
tarunon 30-Jun-17 07:20 AM
ここの文化的な不整合、Apple製APIがchain-caseなのにCodableでスッとできないのは草っていう話題
Avatar
koher 30-Jun-17 07:20 AM
enum絡むライブラリ作ったら名前これにしようと思ってた フーイナム 《Swift 作 Gulliver's Travels (ガリバー旅行記)の中の人間的な理性が徹底している馬; 人間の形をした Yahooを支配する》.
これは Swift 絡みなのはいいとして、なんで enum なの?
07:21
chain-case って言うんだ。
Avatar
t.ae 30-Jun-17 07:21 AM
発音から。ネイティブだったらどう発音するのかわかんないですが
Avatar
koher 30-Jun-17 07:21 AM
ああ、そういうことか < 発音
Avatar
rintaro 30-Jun-17 07:23 AM
swift-package-manager - The Package Manager for the Swift Programming Language
Avatar
koher 30-Jun-17 07:23 AM
Yahoo もガリバー由来なんだ・・・
Yahoo!の名前の由来は英語の「Yet Another Hierarchical Officious Oracle」(さらにもう一つの階層的でお節介な神託)の略だといわれている[57]。また、ファイロとヤンは自分たちのことを「ならずもの」だと考えているので、「粗野な人」という意味がある「Yahoo」(『ガリヴァー旅行記』に登場する野獣の名前が由来)という言葉を選んだと主張している[10]。さらに感嘆符が付いていることに関しては「ヤッホー!」「やったー!」を意味する英語の感動詞「yahoo」と掛けているとも考えられる。
Avatar
t.ae 30-Jun-17 07:25 AM
Package.swiftでの指定はURLなのでハイフンつなぎにしといても問題ないかなぁと思っている。
Avatar
tarunon 30-Jun-17 07:25 AM
別にConvertするわけじゃないからConvertibleは不適切な気がしてきた
Avatar
koher 30-Jun-17 07:25 AM
ほんとだ・・・ < 現状はディレクトリ名
Avatar
tarunon 30-Jun-17 07:25 AM
abstract-enumとかかなぁ (edited)
Avatar
koher 30-Jun-17 07:26 AM
え? EnumNConvertibleEnumN に convert するんじゃないんですか?
Avatar
tarunon 30-Jun-17 07:26 AM
いやそれはその通りなんですが
Avatar
koher 30-Jun-17 07:26 AM
abstract-enum 長いから abstenum とか?
07:27
CustomStringConvertible とかを考えても EnumNConvertible とかならおかしくない気も。
Avatar
tarunon 30-Jun-17 07:27 AM
なるほど
Avatar
koher 30-Jun-17 07:27 AM
N がなかったらどうだろう
Avatar
t.ae 30-Jun-17 07:28 AM
Nm
Avatar
koher 30-Jun-17 07:28 AM
別にライブラリ名だし良さそう?
Avatar
tarunon 30-Jun-17 10:53 AM
がちゃっと書いたけど、これgyb使ってビルド時にOption渡して任意個のEnumサポートできるようにしたいな
Avatar
omochimetaru 30-Jun-17 10:56 AM
gyb、 実行時に $ gyb -D Key=Value でパラメータ渡せるから、できるよ
Avatar
tarunon 30-Jun-17 10:56 AM
おお
Avatar
omochimetaru 30-Jun-17 10:57 AM
cpp-rhetoric - small fundamental library for modern C++ programming.
cpp-rhetoric - small fundamental library for modern C++ programming.
10:57
OptionalとResultがEither2実装になった。
Avatar
tarunon 30-Jun-17 11:00 AM
public func animatedItems<S: AnimatableSectionModelType, O: ObservableType, C0: Reusable, C1: Reusable, C2: Reusable, C3: Reusable, C4: Reusable>(for type0: C0.Type, _ type1: C1.Type, _ type2: C2.Type, _ type3: C3.Type, _ type4: C4.Type) -> (O) -> Disposable where C0: UICollectionViewCell , C1: UICollectionViewCell , C2: UICollectionViewCell , C3: UICollectionViewCell , C4: UICollectionViewCell , S.Item: Enum5Convertible , S.Item.T0 == C0.Dependency , S.Item.T1 == C1.Dependency , S.Item.T2 == C2.Dependency , S.Item.T3 == C3.Dependency , S.Item.T4 == C4.Dependency , O.E == [S] {
使う側がこんな感じの地獄じみた形相になってるから、任意個数サポートできるのはもはや必須の感じがする
Avatar
omochimetaru 30-Jun-17 11:05 AM
www
11:06
cpp-rhetoric - small fundamental library for modern C++ programming.
11:06
指定のディレクトリ配下から *.gybを探して 変換するラッパー。参考にどうぞ。
Avatar
tarunon 30-Jun-17 11:06 AM
あざます
11:07
これUI{Table, Collection}Viewの{Animated, Reload}DataSourceに対応しなきゃいけないから
11:07
Enum5でも5x4で20個関数用意していてバカじゃないのって感じがする
Avatar
moaible 30-Jun-17 11:11 AM
要素全部型定義してるんですね😱
Avatar
tarunon 30-Jun-17 11:11 AM
これがあると
Avatar
omochimetaru 30-Jun-17 11:11 AM
自動生成の機運
Avatar
tarunon 30-Jun-17 11:12 AM
dataSourceObservable .bind(to: tableView.rx.animatedItems(for: MyCell1.self, MyCell2.self)) .disposed(by: disposeBag)
11:12
こんな感じのコードを、ちょっとだけ型定義するだけで書けるようになる
Avatar
moaible 30-Jun-17 11:13 AM
なるほど
Avatar
tarunon 30-Jun-17 11:13 AM
定義側がしんどいのは自動生成でカバーできれば完全勝利だから
Avatar
koher 30-Jun-17 11:29 AM
curry は昔ジェネリック引数14個(?)でコンパイル終わらなくなる問題がありましたが大丈夫そうですか?
Avatar
tarunon 30-Jun-17 11:30 AM
1TableViewに14種類Cell使う人が居たら大丈夫じゃないかもですねw
Avatar
koher 30-Jun-17 11:30 AM
w
Avatar
omochimetaru 30-Jun-17 11:30 AM
ww
Avatar
tarunon 30-Jun-17 11:31 AM
多分、1-14までオーバーロードさせるとそうなるんで、連番で作るのとピンポイントで作れるのを用意しておけば良い気がします
Avatar
moaible 30-Jun-17 01:11 PM
gyb環境構築微妙にハマった... --line-directive= 入れないと ###sourceLocation が各行入るからなんなのかと思った
Avatar
omochimetaru 30-Jun-17 01:12 PM
そうですねw
13:13
cpp-rhetoric - small fundamental library for modern C++ programming.
13:13
わざわざ空にしないといけない
😰 1
Avatar
moaible 30-Jun-17 02:36 PM
Swift gybの環境構築 ふとSwiftのgybが気になったので環境構築を試して見ました gybとは Swift言語開発の副産物のメタプログラミングツールgybがとても良い— おもちメタル (@omochimetaru) 2017年6月30日 gybは「Generate Your Boilerplate」の略称みたいです(gyb --helpより) 具体的に何かと言うと、Swiftの公式リポジトリの中でSwiftコードの自動生成に使われているPython製のテンプレートエンジンになります gybを導入する qiita.com というわけで、こちらを参考に環境構築して見ました まずgyb自体…
Avatar
omochimetaru 30-Jun-17 03:39 PM
###sourceLocationというgyb側のログ?も一緒に出力されてしまうので必須で追加した方が良いです
15:39
これは多分、Swiftコンパイラに対して、ソースコードの本当の位置を教えるための仕組みですね
15:40
gybから生成された.swiftにおける行数を表示したところで
15:40
ほんとうの意味でのソースコードは.swift.gybだから
15:40
それの場所をデバッガに伝えるためのやつ
Avatar
moaible 30-Jun-17 04:07 PM
なるほど、修正しときます🙏
Avatar
omochimetaru 30-Jun-17 04:20 PM
typescriptとかESJSでやるsourcemapがソース自体に埋め込まれてるようなもんですね
04:10
このメールで提案されてるのってここでも何度かでた話を全く同じ提案じゃない?
04:11
右辺値に説明文を書かないといけない !! オペレータ。機能は ! と同じ。
04:13
never型ちゃんとやって preconditionFailure を ?? に並べたらええってレスもついてるな
04:14
スレが70投稿ぐらい伸びてて読みきれん
Avatar
norio_nomura 10-Jul-17 04:24 AM
2017/06/28にkoherさんが #swift にそのリンクを投げて盛り上がってましたよ。
Avatar
omochimetaru 10-Jul-17 04:26 AM
ああ話題自体がここソースだったのか
Avatar
norio_nomura 10-Jul-17 04:37 AM
そのスレッド、僕のメールボックスでは100件になってる。
Avatar
omochimetaru 10-Jul-17 04:54 AM
ブラウザ1ページしか見なかったので全部だとそのくらいありそうです
Avatar
omochimetaru 11-Jul-17 02:18 AM
Swift4のCodableが内部で何をやっているか確認する by @kenmaz on @Qiita http://qiita.com/kenmaz/items/8bfd386ad4a978b6ed6d
ほんの小ネタです。 Swift4から導入されるCodableですが、どういう仕組で実現されているんでしょうか。WWDCのプレゼンによるとCodableを適用すると、encode/decodeを実現するための実装をコンパイラーが生...
02:19
ASTフェーズですでに自動生成コードが展開されてるってことは、ちゃんとSwiftのソースコードとしてコンパイルされてそう
Avatar
tarunon 11-Jul-17 05:07 AM
あれ、Xcode9 beta3、se0110はRevokeされてるけどRxSwiftのテストケースは死屍累々のままだ
05:07
Overloadとの兼ね合いで何か壊れている気がするな…
05:10
理解した、クロージャがOptionalだとぶっ壊れるw
05:15
struct ObservableA<T> { func subscribe(onNext:(T) -> () = { _ in }) { } } ObservableA<(Int, Int)>().subscribe(onNext: { (a, b) in // ok }) struct ObservableB<T> { func subscribe(onNext:((T) -> ())? = nil) { } } ObservableB<(Int, Int)>().subscribe(onNext: { (a, b) in // 死ーん })
Avatar
moaible 11-Jul-17 05:17 AM
Bダメなんですね、見たところ問題なさそうに見える
Avatar
tarunon 11-Jul-17 05:18 AM
後でbugsに上げとこう
05:18
RxSwiftはどうするかな、まだ待った方が良いか…
Avatar
moaible 11-Jul-17 05:28 AM
これって問題なのは一度型変数に入れたタプルをタプルとして解釈できないのが問題なんでしたっけ? (edited)
Avatar
tarunon 11-Jul-17 05:29 AM
タプルを複数引数に分解できないようにするのがse0110、rollbackしたけど、Optionalなクロージャは判定されてないのでse0110の影響が生きている
😇 2
Avatar
moaible 11-Jul-17 05:29 AM
なるほど
Avatar
tarunon 11-Jul-17 05:30 AM
ということだと思います、確かにse0110ロールバックのPRは、Optional考慮してなかったような気がする
05:30
swiftコンパイルできる環境あればこういうの直にpr投げれるな、早く環境作ろう
Avatar
omochimetaru 11-Jul-17 05:47 AM
[omochi@omochi-iMac bin]$ pwd /Users/omochi/work/swift-source/build/Ninja-RelWithDebInfoAssert/swift-macosx-x86_64/bin [omochi@omochi-iMac bin]$ ./swift --version Swift version 4.0-dev (LLVM a15decabe3, Clang 60a12bf739, Swift fcd389b17e) Target: x86_64-apple-macosx10.9
👏 3
05:47
ちょうどいまできた
Avatar
moaible 11-Jul-17 05:47 AM
どのぐらいビルドかかりました?
Avatar
tarunon 11-Jul-17 05:47 AM
はやくMacPro回収しないと
Avatar
omochimetaru 11-Jul-17 05:47 AM
本当はplaygroundでやりたいからtool-chain全部いりにしたいんだけどこの前やった結果それはとてもつらい
05:48
うーん お昼ごはんたべにいってたから
05:48
12:30 〜 14:30 ぐらいかな?
Avatar
moaible 11-Jul-17 05:48 AM
あ、そんなもんなんや
Avatar
omochimetaru 11-Jul-17 05:48 AM
もうちょっと速いかも
05:49
飯に行ってたから終わった時刻が正確にわからない(飯に2時間いっていたという意味ではないw
Avatar
moaible 11-Jul-17 05:49 AM
ww なるほど、ありがとうございます
Avatar
omochimetaru 11-Jul-17 05:50 AM
iMac Corei7 3.6GHz / memory 16GB / SSD
🙇 1
Avatar
omochimetaru 11-Jul-17 06:01 AM
xcode9.3betaに同梱されてるやつとswift-4.0-branchって何が違うんだろう
06:01
githubでコミットの差分みたらええんか
Avatar
rintaro 11-Jul-17 06:01 AM
swift - The Swift Programming Language
Avatar
omochimetaru 11-Jul-17 06:02 AM
ありがとうございます
06:02
ディスクは19Gつかった
06:02
これtimemachineはずしとこ
06:04
ちょうどrintaroさんのコミットからだw
Avatar
norio_nomura 11-Jul-17 09:34 AM
そうか、Xcode 9 beta 3はCodableの実装がまだ古いのか。
😳 1
Avatar
tarunon 11-Jul-17 10:43 AM
例のOptionalですかね
Avatar
norio_nomura 11-Jul-17 10:45 AM
Avatar
tarunon 11-Jul-17 10:28 PM
https://github.com/apple/swift/pull/10881 Optionalのclosureでtupleが分解できない問題治してもらえた。はやいw (edited)
…jection. There was an oversight in the exception that was added to SE-0110 to maintain compatibility for closure arguments. We were not allowing optional injection to happen for the closure being ...
❤ 4
Avatar
tarunon 12-Jul-17 06:07 AM
なんかbugs.swift.orgのチケットのステータス、今どうなってるのか不明でレポートしてもそれが解決したのかわかりにくいw
06:08
昨日報告したこれ https://bugs.swift.org/browse/SR-5433 は、もうPRがマージされてて見た感じ解決済みなんだけど、チケットは相変わらず未解決だし。
Avatar
koher 12-Jul-17 08:25 AM
ひそかに(?) @rintaro さんの第二弾が投稿されてる。前回のと合わせてビルドしてテストできるようになるので、これに従えば swift リポジトリに PR 出せそう。 http://qiita.com/rintaro/items/2f84776cf1629150b312
この記事は、 Swift.org のオープンソース Swift の開発に参加してみたい方のためのものです。普通にSwiftでアプリの開発をするのにはまったく役立たない知識です。 Swift コンパイラのテスト環境は普通のプロジェクト...
😀 1
Avatar
tarunon 12-Jul-17 08:35 AM
Twitterでpublishしてたからひっそりではないですねw
Avatar
koher 12-Jul-17 08:36 AM
お、 Twitter みてませんでした😅
Avatar
norio_nomura 12-Jul-17 09:04 AM
XCTestXFAIL欲しい
09:11
litはテキストファイルならなんでも良いので、.mdにテストを書いたりできるのが面白いと思った。 https://github.com/apple/swift-integration-tests/blob/master/swift-package-init-exec.md
swift-integration-tests - Automated tests for validating the generated Swift snapshots behave correctly
Avatar
rintaro 12-Jul-17 09:13 AM
swift-integration-tests - Automated tests for validating the generated Swift snapshots behave correctly
Avatar
norio_nomura 12-Jul-17 09:28 AM
あ、そうですね。
Avatar
koher 13-Jul-17 01:33 AM
↓なるほどー、改行をエスケープしたくなるのか。 https://github.com/apple/swift-evolution/blob/master/proposals/0182-newline-escape-in-strings.md
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
t.ae 13-Jul-17 01:45 AM
XCTestといえばAssert系の関数を自前実装できるようにしてほしい。 特にXCTAssertEqualWithAcuracyはフィールドごとに確認するので増えるほど書くのがきつくなる
stcuct Hoge { val a: Float } let x = Hoge(a: 0) let y = Hoge(a: 0) XCTAssertEqualWithAcuracy(x, y, accuracy: 1e-10)
かといって関数に切り出すとXCodeで停止地点が分かりづらくなる。 XCTAsserEqualEquatableを実装するだけで使えるので 同様にNealyEquatableみたいなプロトコルを切ってXCTestがそれを使うXCTAssertEqualWithAcuracyを用意してくれるのがベストかな。
Avatar
omochimetaru 13-Jul-17 01:46 AM
XCTestを捨てたら良いのでは
01:47
その問題はXCTestとか昔のJUnitとかのテストフレームワークがずっと抱えてきた問題で
01:47
最近のだとそういうオペレータをユーザ定義できるのが主流だと思う
Avatar
t.ae 13-Jul-17 01:48 AM
なるほど。 といってswiftの場合swift testとかで結構密接に結びついてるのでこちらからどうこうもしにくい気が。
01:48
XCTest上で動く別のテストフレームワークを用意する?とかができるのかな
Avatar
omochimetaru 13-Jul-17 01:49 AM
詳しくは知らないけど誰かが知ってそう・・・
Avatar
koher 13-Jul-17 01:51 AM
Carthage - A simple, decentralized dependency manager for Cocoa
01:53
あ、 Carthage を SwiftPM でビルドする話。
Avatar
norio_nomura 13-Jul-17 01:53 AM
かといって関数に切り出すとXCodeで停止地点が分かりづらくなる。
切り出した関数に…file: StaticString = #file, line: UInt = #line)とかつけると良いのでは。
Avatar
t.ae 13-Jul-17 01:55 AM
それでもいいですけど標準だと視覚的にぱっとわかりますからね……
Avatar
koher 13-Jul-17 01:55 AM
Quick - The Swift (and Objective-C) testing framework.
Avatar
t.ae 13-Jul-17 01:56 AM
どうやってXCode上で色々出来てるんだろうと思ったらXCTestにつながってるわけですか。 swift testもできるのかな?
Avatar
koher 13-Jul-17 01:56 AM
そりゃ継承してるんだからできるんじゃない?< swift test
Avatar
norio_nomura 13-Jul-17 01:57 AM
個人的な意見としては、SwiftPMを使うならQuickとNimbleは使いたくないな。
Avatar
omochimetaru 13-Jul-17 01:57 AM
Avatar
t.ae 13-Jul-17 01:57 AM
carthageのPackage.swiftはdependenciesがなんか複雑になってますね……
Avatar
omochimetaru 13-Jul-17 01:57 AM
なんかトレンドとかあったらしりたいです
Avatar
koher 13-Jul-17 01:58 AM
テストのときだけ Quick を使いたいからじゃない? < 複雑
Avatar
t.ae 13-Jul-17 01:58 AM
そうですね。 https://github.com/Carthage/Carthage/blob/master/Package.swift#L4-L6 このへん何なんだろうってなる
Carthage - A simple, decentralized dependency manager for Cocoa
01:59
ただの環境変数か
Avatar
koher 13-Jul-17 01:59 AM
Quick - The Swift (and Objective-C) testing framework.
02:01
We still run swift test on CI using separated .Package.test.swift. This is the same as Carthage/Commandant#83.
Avatar
omochimetaru 13-Jul-17 02:01 AM
script: + - mv .Package.test.swift Package.swift
02:01
これがあるし
02:01
すり替えるんじゃないかな、自力で
Avatar
norio_nomura 13-Jul-17 02:02 AM
Swift 3 では結局testDependenciesがなかったので、テストの時だけ使う依存を実現してる。
Avatar
koher 13-Jul-17 02:02 AM
Currently "Test-only dependencies" feature is disabled in the Swift Package Manager. It was implemented initially, but was removed in this commit.
https://stackoverflow.com/a/41407032
I've seen mentions of test-only dependencies when using the Swift package manager but haven't been able to get them to work. For example: https://lists.swift.org/pipermail/swift-evolution/Week-of-...
02:03
おおお、初期に testDependencies 見た気がしてたんだけど使えなくなってるのか・・・
02:04
Remove testDependencies from PackageDescription This feature was supposed to support dependencies only for the root package but at some point it stopped working however the API still remained open. This patch removes the public API. This is a valid and desired feature which is supposed to come back after it goes through proper review on swift evolution.
https://github.com/apple/swift-package-manager/commit/34b7826cb586b0769ea5f60a7718d7de599ce27f
This feature was supposed to support dependencies only for the root package but at some point it stopped working however the API still remained open. This patch removes the public API. This is a va...
02:05
それだと Quick とか使いたくないですね・・・。
Avatar
t.ae 13-Jul-17 02:05 AM
swift evolutionのほうは誰も出して無いのかな……
Avatar
norio_nomura 13-Jul-17 02:05 AM
テスト用のPackage.swiftを用意してたけど、環境変数で切り替えられることをikesyoさんに伝えたら使ってくれた。 (edited)
02:06
Swift 4のPackage ManifestでQuick, Nimbleがどの様に使えるかは、僕は知らない。
Avatar
omochimetaru 13-Jul-17 02:07 AM
SWIFTPM_TEST_Carthage
ああこれはSPMが定義してくれるのか。
02:07
なんか若干矛盾を感じるな・・・ SPMが定義するならSPM上のSwift APIで良いのでは・・・
Avatar
koher 13-Jul-17 02:08 AM
改めて考えると、テストって本体と別パッケージだと思うんですけど、本体用に作った Packagedependencies がテストからも使えるのなんか変な気も。
Avatar
t.ae 13-Jul-17 02:08 AM
そこはテストが間接的に依存してるからいいのでは?
Avatar
omochimetaru 13-Jul-17 02:08 AM
@koher 使えないとメソッド引数の型とかに依存ライブラリの型が使われてたらテストできなくないですか?
Avatar
koher 13-Jul-17 02:09 AM
まあ実用面で考えるとテスト用のパッケージは本体に付随して生まれるものということでいいのかなぁ。
Avatar
omochimetaru 13-Jul-17 02:10 AM
てか本来的には
02:10
アプリターゲットとテストターゲットをわけて、テストターゲットがアプリターゲットに依存
Avatar
norio_nomura 13-Jul-17 02:10 AM
> SWIFTPM_TEST_Carthage ああこれはSPMが定義してくれるのか。
Makefileで実行するときに設定してます。 https://github.com/Carthage/Carthage/blob/master/Makefile#L82
Carthage - A simple, decentralized dependency manager for Cocoa
Avatar
omochimetaru 13-Jul-17 02:10 AM
っていう構造が自然な気がするけど
02:11
Carthageの構造はあくまで Carthageパッケージがテスト用の状態に変化するっていう
02:11
作りなんですね
02:11
@norio_nomura ああ、なるほど、自前でタスクランナーかましてるなら納得です。最初分岐みたときそれを想像しました。
02:12
環境変数で切り替えられることをikesyoさんに伝えたら使ってくれた。(
これを誤読しました。
Avatar
norio_nomura 13-Jul-17 02:14 AM
Package.swiftがサンドボックス内で解釈される際に、SwiftPMがあえて環境変数を引き継ぐ様にしてるので、あながち間違いでもない。
02:15
最初、環境変数を処理分岐に使えたのは意図せぬ挙動だったけど、サンドボックス化の際にサポートされた挙動になった、という感じ。
Avatar
omochimetaru 13-Jul-17 02:16 AM
ふむふむ。
02:19
「サンドボックス」ってここらへんの話ですか?
Avatar
norio_nomura 13-Jul-17 02:19 AM
そう。
Avatar
omochimetaru 13-Jul-17 02:19 AM
$ which -a sandbox-exec /usr/bin/sandbox-exec
02:19
なんかはいってた
02:20
DESCRIPTION The sandbox-exec command is DEPRECATED. Developers who wish to sandbox an app should instead adopt the App Sandbox feature described in the App Sandbox Design Guide.
02:20
man引いたらいきなりDEPRECATEDって書いてあったw
02:21
macになんかあった仕組みかあ
Avatar
norio_nomura 13-Jul-17 02:22 AM
SwiftPMのSlackでその辺りが話されてたのを読んでました。
Avatar
omochimetaru 13-Jul-17 02:22 AM
なるほど
Avatar
norio_nomura 13-Jul-17 02:26 AM
sandbox-execを使う様にしたコミットには環境変数がらみが特に書かれてないぽいから「環境変数をあえて渡す」というのは、チャットの中だけの話だったかも。
Avatar
omochimetaru 13-Jul-17 02:28 AM
なるほど。
Avatar
norio_nomura 13-Jul-17 02:34 AM
そういえば、Xcode 9のXCTestに追加されたAPIって、もうswift-corelibs-xctestに移植されたのかな?
02:38
なさげ…
Avatar
t.ae 13-Jul-17 02:53 AM
@norio_nomura 先程の#lineを使うってこれのことですか。 http://masilotti.com/xctest-helpers/ そもそもrecordFailureの存在を知らなくてログに行番号出るだけじゃ分かりにくいとか思っていました。
How to extract XCTest helper methods and keep sane failure messages.
Avatar
norio_nomura 13-Jul-17 02:54 AM
そそ。XCTAssert*()シリーズにも渡せます。
Avatar
t.ae 13-Jul-17 02:54 AM
テストフレームワークが欲しいとかいうわけじゃないので僕の問題はこれで解決しそうです。 ありがとうございます!
03:00
XCTAssert*()シリーズに渡せるってのは何でしょう? recordFailureXCTestCaseのメソッドなのでXCTAssert*()のようにトップレベルのを定義するにはデフォルト引数で呼び出し元のselfを渡すとかするのかなぁと思ったのですが。
03:01
以前ここで話されたデフォルト引数にselfを渡す話をよく覚えていない……
Avatar
omochimetaru 13-Jul-17 03:01 AM
XCTAssertEqualにline引数があるんじゃ? (edited)
Avatar
t.ae 13-Jul-17 03:04 AM
ありますね。 XCTestCaseは引数にないのでどこから渡っているのか謎。 別の仕組みになっているんだろうか。
Avatar
omochimetaru 13-Jul-17 03:05 AM
XCTestCaseは関数じゃなくてクラスでは??
Avatar
t.ae 13-Jul-17 03:06 AM
recordFailureXCTestCaseのメソッドなんですよ。 で、XCTAssert*()はトップレベルなのでrecordFailureが使えない(はず)
03:08
まぁ新しいのをXCTestCaseのextensionにすればいいんですが XCTAssert*()と同名を用いると例のバグ?でトップレベルのほうが見えなくなる。 (edited)
Avatar
omochimetaru 13-Jul-17 03:11 AM
APIの外側にあるランナーが「現在のTestCase」を保持していて、XCAssertEqualは内部でそれを拾ってる気がする
Avatar
norio_nomura 13-Jul-17 03:15 AM
SwiftLintで、SwiftLintのソースコード自体をlintしてviolationがあったらテストの失敗として記録する仕組みを作りました。そこではrecordFailure() ではなく XCTFail() を使ってました。 https://github.com/realm/SwiftLint/blob/master/Tests/SwiftLintFrameworkTests/IntegrationTests.swift#L35
SwiftLint - A tool to enforce Swift style and conventions.
Avatar
t.ae 13-Jul-17 03:16 AM
ああ、recordFailureを使うんじゃなくて内部でfile, line指定付きのXCTAssert*()を使えってことですね。 間違った方向に進んでました。
Avatar
tarunon 13-Jul-17 05:41 AM
#swift の array[...]ハック、引数を@autoclosure () -> Tで表現すれば割と何でも出来るな、ということに気がついた
05:41
関数である必要もなくなる
Avatar
omochimetaru 13-Jul-17 05:42 AM
ふむ
Avatar
tarunon 13-Jul-17 05:43 AM
そうするとつまり
05:44
enum Foo { static var foo: Foo { fatalError() } } func bar(_ foo: @autoclosure () -> Foo, ....) { ... } bar(.foo, ....)
これが可能になる
05:45
何やりたいのか理解するのが非常に難しいw
05:45
第一引数に与える型でオーバーロードを実現したいって話なんだけどね
Avatar
omochimetaru 13-Jul-17 05:45 AM
Foo.foo が実際には生成されないのがポイント?
Avatar
tarunon 13-Jul-17 05:46 AM
Foo.fooの評価は、bar内でfoo()をするまで実行されない。したがってbarの中で使っていなければ…というのがポイント
Avatar
rintaro 13-Jul-17 05:47 AM
delegate.scrollView(scrollView, .didScroll) とかにいいかも (edited)
Avatar
omochimetaru 13-Jul-17 05:47 AM
struct Foo {} let foo = Foo() func bar(foo: Foo, ....) { ... } bar(foo, ....)
そもそもこれじゃ駄目な理由は?
Avatar
tarunon 13-Jul-17 05:48 AM
グローバルfooは少なくともなし
05:49
struct Foo { static var foo = Foo() } ならまあ差はそれほど無いのかもしれない。
05:49
実態渡してるから都度コピー出るけど最適化で消えるんですかね
Avatar
omochimetaru 13-Jul-17 05:49 AM
それだと .foo で書けるね
05:49
そもそも0バイトの型になって消えてそう。
Avatar
tarunon 13-Jul-17 05:50 AM
最適化で無になるなら、差は無いと言い切って良さそうだ
Avatar
omochimetaru 13-Jul-17 05:52 AM
struct BarOverloads { static let foo = BarFoo() static let poo = BarPoo() } func bar(_ overload: BarFoo, ...) func bar(_ overload: BarPoo, ...) bar(.foo, ...) // できない bar(.poo, ...)
(edited)
05:52
あ、だめだな
05:53
うまく定義をまとめられないかとおもったけどダメだった
Avatar
tarunon 13-Jul-17 05:53 AM
struct Bar { struct Foo { static let foo = Foo() } struct Poo { static let poo = Poo() } } func bar(_ overload: Bar.Foo, ...) func bar(_ overload: Bar.Poo, ...) bar(.foo, ...) bar(.poo, ...)
(edited)
05:53
これならおk
Avatar
omochimetaru 13-Jul-17 05:54 AM
なるほどw
Avatar
d_date 13-Jul-17 06:17 AM
朝ラトナーがメーリスに投げてましたけど、Multi-line Stringのリファイメントが始まったみたいですね。改行に \ を使う感じで。 https://github.com/apple/swift-evolution/blob/master/proposals/0182-newline-escape-in-strings.md (edited)
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
omochimetaru 13-Jul-17 06:19 AM
これはうれしい気がする
Avatar
koher 13-Jul-17 06:25 AM
これいいですよね。
Avatar
d_date 13-Jul-17 08:04 AM
いいですよね。メーリスみてても評判よさそう
Avatar
koher 13-Jul-17 03:11 PM
swift-evolution で、↑の改行エスケープを認めると↓が思いがけないバグになるって意見が出てる。なるほど。
let s = """ ... In Windows you have paths like C:\ ... """
Avatar
omochimetaru 13-Jul-17 03:21 PM
Windowsの民はパス文字列にバックスラッシュがあって思わぬことが起きるのに慣れてて警戒するから大丈夫
Avatar
koher 13-Jul-17 03:24 PM
現仕様だと↑はコンパイルエラーになって \\\ に直さないといけないけど、新使用だとコンパイルエラーにならないから問題だと。特に """ だからといって文字列コピペしてきたときとかに問題起こりそう。
Avatar
rintaro 13-Jul-17 03:28 PM
それ言い出しちゃうと c:\news とかもそうなんで。ちょっと弱い。
Avatar
koher 13-Jul-17 03:30 PM
それはコンパイルエラーになるから直せるけど、たまたま行末に紛れてたら見過ごしそうじゃないですか?
Avatar
omochimetaru 13-Jul-17 03:30 PM
nがにくっついて\nになるからコンパイルエラーにならないという意味では?
Avatar
koher 13-Jul-17 03:30 PM
ああ、そういうことか。
Avatar
omochimetaru 13-Jul-17 03:31 PM
つまり現状でもコンパイルエラーにならないが意図せず出現した \ などによって思わぬ変化は起きるのだから同じだよと
Avatar
koher 13-Jul-17 03:31 PM
なるほど、たしかに。
Avatar
norio_nomura 15-Jul-17 01:23 AM
Optionalのclosureでtupleが分解できない問題治してもらえた。はやいw
swift-4.0-DEVELOPMENT-SNAPSHOT-2017-07-11-a以降で直ってるぽいですね。
💞 1
Avatar
koher 20-Jul-17 01:00 PM
WWDC の "What's New in Swift" で COW Existential Buffers について触れられてますが、 Existential じゃない普通の struct でもサイズが大きいと勝手に最適化されたりするんでしょうか?どこかで触れられてましたっけ? https://developer.apple.com/videos/play/wwdc2017/402/
Swift 4 continues the evolution of the safe, fast, and expressive language, with better performance and new features. Learn about the new...
Avatar
omochimetaru 20-Jul-17 01:02 PM
自分が調べた限りではstructについては大きくなってもヒープ化はされなかったですよ
13:02
その話なのかはわからないですが
Avatar
koher 20-Jul-17 01:02 PM
↑の COW Existential Buffer は Swift 4 からの話なので、新しく何かあるのかも?
Avatar
omochimetaru 20-Jul-17 01:03 PM
あと、ヒープ化が標準で、小さい時のスタック化の方が最適化だと思う
13:03
なるほど
Avatar
koher 20-Jul-17 01:06 PM
(興味があれば)↑のビデオの15:30あたりから話してる。
Avatar
omochimetaru 20-Jul-17 01:07 PM
興味アリアリ
Avatar
rintaro 20-Jul-17 01:20 PM
https://github.com/apple/swift/pull/8909 これの話かと思ったら違った。
radar rdar://problem/28680453 Reduce the size of the text area (code size of the compiled output) by changing the way we generate LLVM IR for loadable types: We do a SIL level transformation, durin...
13:23
https://github.com/apple/swift/pull/9142 こっちか。大きい値型を自動的にアドレス渡しにしてコードサイズを減らそうっていう件。
radar rdar://problem/28680453 This is an updated version of #8909 It addresses the code review comments and splits the PR into multiple commits Reduce the size of the text area (code size of the co...
13:24
が実装されたんだけど、問題起きて disable されちゃいました。4.0 には入らないと思います。 https://github.com/apple/swift/pull/9452
radar rdar://problem/32064645 Disable large types irgen pass (for now) Swift 4.0 PR #9447
😂 1
Avatar
koher 20-Jul-17 01:27 PM
we'll get back to this transformation at some point, making sure it is truly great, but it is not going to be re-enabled on the 4.0 branch.
13:27
残念・・・。
Avatar
tarunon 20-Jul-17 01:27 PM
https://teratail.com/questions/13866 ここで岸川さんが言ってる、
structは24バイトを越えるとheapに追い出されます。
とは別の話ですか?
Swiftのstructはclassとよく似ているところがありますが、どのように使い分けるのでしょうか。structの性質を使った、実際の実装パターンなどありましたらご教授をお願いできればと思います。
Avatar
omochimetaru 20-Jul-17 01:29 PM
32バイトのstructでも、スタックに置かれていることが分かります。
どんなコードを書いたらstructはヒープに置かれるんですか? また、あたなのSwiftのバージョンはいくつですか?(ちなみに上記の結果はSwift1.2です。) 仮にstructがヒープに置かれた場合、CやObjective-Cとの互換性はどうなりますか?
13:29
レスで反論されてるね
Avatar
tarunon 20-Jul-17 01:29 PM
お、ほんとだ
Avatar
omochimetaru 20-Jul-17 01:29 PM
俺もおかしいと思った
Avatar
koher 20-Jul-17 01:30 PM
岸川さんの情報源は何だったのか気になる・・・
Avatar
rintaro 20-Jul-17 01:30 PM
Existential に入れたときの挙動とごっちゃになったのかな?
Avatar
omochimetaru 20-Jul-17 01:31 PM
Existentialのときはヒープ退避しますね、24で
13:31
24までは収まるから25以上で、か
Avatar
koher 20-Jul-17 01:35 PM
そのヒープ退避されたバッファの扱いがSwift4でCOWになる? (edited)
13:36
これまでは代入の度にヒープに新しい領域確保してコピーしてたってこと??
Avatar
omochimetaru 20-Jul-17 01:37 PM
僕がLLVM読んだときはそんなふうに見えた
13:37
C++のstd::stringみたいな感じで。
Avatar
koher 20-Jul-17 01:39 PM
std::string は確か COW だったけど COW 止めたんよね?
Avatar
omochimetaru 20-Jul-17 01:39 PM
ポインタを持った外側の構造体(existential)がコピーされるときに、その参照先の実態をヒープ上で複製する
13:39
そうですね。
13:39
24バイトまでのSSO (Small String Optimization)っていって
13:39
それは残ってる
13:40
全く同じですね
Avatar
koher 20-Jul-17 01:41 PM
マルチスレッドでリファレンスカウント操作するところで同期しないといけなくてパフォーマンス上の問題があったって聞いたんだけど、 Swift の Array 等の場合はマルチスレッドをサポートしないことで問題を回避している??
Avatar
omochimetaru 20-Jul-17 01:41 PM
Swiftの参照カウンタもスレッドセーフっぽかったですよ
13:41
atomicなんたらとか出てきた
Avatar
koher 20-Jul-17 01:44 PM
うーん、昔はアプリレベルだと問題ないんじゃない?と思ったけど、Swiftをあらゆる用途で使おうとすると同じ問題にひっかかりそうな気がするんだけどどういう判断なんだろう?
Avatar
omochimetaru 20-Jul-17 01:45 PM
僕はそもそも参照カウンタ操作が遅いっていうのがあんまり信じられない
13:45
atomic操作になるんで
Avatar
koher 20-Jul-17 01:46 PM
インクリメントやデクリメントはatomicにできても
13:46
COWの参照カウントチェックの部分は同期しないといけないのでは?
Avatar
omochimetaru 20-Jul-17 01:46 PM
13:47
インクリメントして、結果をもらうところまでがアトミックです
13:47
デクリメントして0になるスレッドはひとつだけだから
13:47
0かどうか観察する分岐はロックしない
Avatar
koher 20-Jul-17 01:48 PM
Arrayの要素を変更しようとしてバッファの参照カウントを確認した結果1だったからコピーしなくていいやとなったけど、それと同時に別スレッドで代入されて参照カウントが2になったらバグらない? (edited)
Avatar
rintaro 20-Jul-17 01:48 PM
https://github.com/apple/swift/pull/7557 非アトミック版の参照カウンタを使うっていうオプションがあります。興味あれば。
Avatar
koher 20-Jul-17 01:49 PM
おお、そんなものが・・・😶
Avatar
omochimetaru 20-Jul-17 01:54 PM
ソースレイアウトが結構変わってて探し中
Avatar
koher 20-Jul-17 01:54 PM
うーん、単に代入前に変更されたように見えるだけか?
Avatar
omochimetaru 20-Jul-17 01:54 PM
Arrayの要素を変更しようとしてバッファの参照カウントを確認した結果1だったからコピーしなくていいやとなったけど、それと同時に別スレッドで代入されて参照カウントが2になったらバグらない?
これはデクリメントじゃなくてコピーするときの話ですよね
13:55
えーっと・・・
13:55
1だったときは
13:55
そもそも1つのスレッドからしか参照されてないのでは
Avatar
koher 20-Jul-17 01:56 PM
同じ変数が複数スレッドから参照されることはあるのでは?
Avatar
omochimetaru 20-Jul-17 01:57 PM
そのためにはカウンタが2になりません?
Avatar
koher 20-Jul-17 01:58 PM
↓のようにしても参照カウントは 1 のままじゃないの?
var a = [2, 3, 5, 7] // スレッドA a[2] = 4 print(a) // スレッドB a[3] = 8 print(a)
(edited)
Avatar
omochimetaru 20-Jul-17 01:59 PM
ちょっと僕も考えながらなので不正確かもしれないですが (edited)
13:59
まずスレッドっていうのは
13:59
関数ポインタと任意ポインタのペアでエントリするのが一番ローレイヤにあって
13:59
Swift上で考えると
13:59
startThread( closure: () -> Void )
13:59
な処理を呼び出すことになって
13:59
そのコードだと
14:00
var a = [2, 3, 5, 7] a[2] = 4 startThread { a[3] = 8 }
14:03
Swiftって参照キャプチャなんだっけ・・・
14:04
func startThread(f: @escaping () -> Void) { f() } func main() { var a = [2, 3, 5] a[0] = 88 startThread { a[1] = 99 } print(a) // [88, 99, 5] } main()
Avatar
koher 20-Jul-17 02:04 PM
今ってバッファは struct である Array に包まれてるから
14:05
バッファがキャプチャされるわけではなくない?
14:06
var a = 2 let foo: () -> () = { a += 1 } foo() print(a) // 3
14:06
↑から、値がキャプチャされるときにコピーされてるわけではないことがわかる。
Avatar
omochimetaru 20-Jul-17 02:07 PM
えーっとそうか思い出した
14:08
キャプチャがおきるときは、キャプチャされてる変数をフィールドにもつスコープオブジェクトが作られていて
14:08
クロージャがエスケープするときはそのスコープオブジェクト自体がヒープにいるんだ (edited)
14:09
バッファがキャプチャされるわけではなくない?
それはそうですね
14:09
ラッパーstructのArrayがコピーされるときに
Avatar
koher 20-Jul-17 02:09 PM
そうなんだ。それって実行時に決まるの?
Avatar
omochimetaru 20-Jul-17 02:09 PM
いや
14:09
@escaping
14:10
あるなしでわかる
14:10
@nonescaping なときはキャプチャされていても
14:10
スタックメモリをポインタ参照させればいいから
14:10
早くなる
Avatar
koher 20-Jul-17 02:11 PM
↓みたいなケースでは、極稀なケースのために毎回ヒープにスコープオブジェクトが確保される??
var a = 42 if random() < 0.0001 { foo = { print(a) } }
Avatar
omochimetaru 20-Jul-17 02:11 PM
それだけなら foo がエスケープしてないからならない (edited)
Avatar
koher 20-Jul-17 02:12 PM
foo はグローバル変数かなにか
Avatar
omochimetaru 20-Jul-17 02:12 PM
毎回、じゃ、無い気がする。その5行について1個
14:13
ん?ループもないからそもそも1回か (edited)
14:13
とりあえず、aはスタック上には無いと思います
Avatar
koher 20-Jul-17 02:14 PM
var foo: () -> () = {} func bar() { var a = 42 if random() < 0.0001 { foo = { print(a) } } } for _ in 1...10000000 { bar() }
14:14
↑みたいなイメージ。
Avatar
omochimetaru 20-Jul-17 02:14 PM
はい、その場合、ヒープにアロケート/でアロケートしまくると思ってます。
Avatar
koher 20-Jul-17 02:15 PM
bar のコールのほとんどではスタックで済ませられるはずだけど、
14:15
毎回ヒープになるのか・・・。
Avatar
omochimetaru 20-Jul-17 02:15 PM
ArrayのCOWは、mutatingなメソッドを呼び出すとき(たとえば、 a[0] = 99 に、バッファストレージインスタンスの参照カウンタを見て、1ならそのまま書き換える、2以上ならディープコピーする、だから・・・
Avatar
koher 20-Jul-17 02:15 PM
ディープコピーするの?シャローでは?
Avatar
omochimetaru 20-Jul-17 02:16 PM
ストレージの先の参照型はクローンしないという意味ではシャローですね
14:16
ストレージ自体をクローンする、っていいたかった
Avatar
koher 20-Jul-17 02:18 PM
さっきの話だと、↓みたいにしても a のスコープ自体がヒープに確保されてるから a のバッファへの参照カウントは常に 1 になりそう。
var a = [2, 3, 5, 7] // スレッドA startThread { a[2] = 4 print(a) } // スレッドB startThread { a[3] = 8 print(a) }
Avatar
omochimetaru 20-Jul-17 02:19 PM
えーっと・・・そうですね、ヒープ上にあるスタックオブジェクトのカウントが最大3になって、
14:19
スタックオブジェクトのフィールドに a の実体が1つだけあって
14:19
その内部のストレージのカウントもずっと1ですね (edited)
14:19
そのコード、 a[2] = 4 とかを、ユーザ側で ロックしないとバグりそう?
14:20
スレッドが終了するタイミングでスタックオブジェクトのカウンタが減っていって、スレッドA,B、メインが終わった時点で0になってヒープから a の実体が消えて、その先のストレージも消える。
Avatar
koher 20-Jul-17 02:21 PM
問題は参照カウントのインクリメント/デクリメント自体が atomic だったとしても、参照カウントチェック→更新までの間に参照カウントが変化するとCOWが壊れて値型としての挙動がおかしくなることがあり得るか (edited)
Avatar
omochimetaru 20-Jul-17 02:21 PM
えっとつまり、ランタイムの参照カウンタレベルでは壊れないけど、それよりうえのArray自体がスレッドアンセーフなのでそのコードはバグってる、
Avatar
koher 20-Jul-17 02:22 PM
Array がスレッドアンセーフなのと、 COW がスレッドセーフかどうかと、参照カウンタがスレッドセーフなことは独立な気がする。
Avatar
omochimetaru 20-Jul-17 02:23 PM
そうですね
14:23
僕が最初から言いたいのは
Avatar
koher 20-Jul-17 02:23 PM
それとも、 Array がスレッドアンセーフな時点で Array の COW もスレッドセーフである必要はない?
Avatar
omochimetaru 20-Jul-17 02:23 PM
参照カウンタがスレッドセーフって話
14:23
で、 それとも、 Array がスレッドアンセーフな時点で Array の COW もスレッドセーフである必要はない? これがYESだと思います。
14:23
あ、イエスとかいうとわかりにくいな
Avatar
koher 20-Jul-17 02:23 PM
英語と日本語でひっくりかえるやつだw
Avatar
omochimetaru 20-Jul-17 02:24 PM
Array 自体がスレッドアンセーフな時点で、 ArrayのCOWだけのスレッドセーフティーを考える意味がなくて、それもアンセーフ
Avatar
koher 20-Jul-17 02:24 PM
それなら参照カウンタはatomicでオーバーヘッドのない1命令で済ませられるなら、 Array のCOWに同期のオーバーヘッドはないと。
14:25
C++ のかつての std::string はスレッドセーフにしようとしたから問題があったってこと?
Avatar
omochimetaru 20-Jul-17 02:25 PM
COW特有の、1かどうかみる、というところのややこしい話はArrayをロックして使ってね、という範疇で解決する?
14:26
std::string 自体はスレッドセーフじゃないと思うんだよなあ
Avatar
koher 20-Jul-17 02:26 PM
Array をロックして使ってれっば問題は起こらない気がする。
14:26
そうすると std::string が COW でなくなったのは別の理由なのかな?
Avatar
omochimetaru 20-Jul-17 02:27 PM
この記事はC++ Advent Calendar 2013の15日目にエントリしています。 内容はC++標準ライブラリとスレッドセーフに関する解説になります。 flickr / rennasverden もくじ What's スレッドセーフ? スレッドセーフという幻想 基本型とデータ競合 C++標準ライブラリとデータ競合 C++標準ライブラリ:シーケンスコンテナ編 C++標準ライブラリ:連想コンテナ編 スレッドセーフ RELOADED 基本的なスレッドセーフ保証 std::shared_ptr std::rand() std::cout (本文のみ約9000字) はじめに マルチスレッド…
14:28
Q3. std::stringクラスはスレッドセーフですか? Q3. 「同時アクセスが全て読み込み操作(constメンバ関数相当呼び出し)であれば安全」というスレッドセーフ性レベルが保証される。
14:28
この人はC++界隈で強くて有名な人
14:28
「readonlyならば安全」という「レベル」 というのが答えらしい
Avatar
koher 20-Jul-17 02:28 PM
今の std::string と COW だった頃の std::string はまた別かもしれない・・・
Avatar
omochimetaru 20-Jul-17 02:28 PM
readonlyならば、ってことは、COWは関係ないですね
14:29
そうなんですけど、
14:29
C++11になるまで
Avatar
koher 20-Jul-17 02:29 PM
COW じゃなくなった経緯がわからないと何とも言えなさそう。
Avatar
omochimetaru 20-Jul-17 02:29 PM
C++11スレッドサポートの文脈では新規クラス追加ばかりが注目されています。このような華やかな表舞台の裏側では、以前からあるstd::stringやstd::vectorといったクラス群に対して、スレッドサポートに関連する重要なルールが明確化されたことは知っていますか?
14:29
C++11で std::thread が入るときにこの規格がちゃんと整理されたって話がこの記事に同時に書いてあるので
14:30
C++03以前でもしスレッドセーフだったとしたら、ライブラリが善意でがんばってた、だけの話が気がする
14:30
C++11標準ライブラリのスレッド安全性Add Star
C++ C++11標準ライブラリが提供する機能とスレッド安全性(thread safety)についてのメモ*1。C++03以前では処理系依存。 http://d.hatena.ne.jp/yohhoy/20120513/p1
14:30
処理系依存だったそうな
Avatar
koher 20-Jul-17 02:30 PM
このようなCOWによる文字列クラスの実装は、30年前はともかく、今となってはとても効率が悪い。なぜならば、マルチコア、マルチスレッドが当たり前になってしまったからだ。今は文字列クラスをCOWで実装すべきパフォーマンス上の理由がないので、C++11では、COWで実装することは規格で禁止された。
https://cpplover.blogspot.jp/2013/12/c03c11_29.html
今日も今日とて、C++03とC++11の違いを解説する。今回は、文字列ライブラリー編だ。 変更: basic_stringをリファレンスカウントで実装することを禁止 C++が設計中の時代は、文字列を保持するストレージを文字列クラスで共有して、参照数を記録しておき、変...
Avatar
omochimetaru 20-Jul-17 02:31 PM
あー僕が最初にこの話題みたのこの記事かも。
14:32
なぜならば、マルチコア、マルチスレッドが当たり前になってしまったからだ。今は文字列クラスをCOWで実装すべきパフォーマンス上の理由がないので、C++11では、COWで実装することは規格で禁止された。
このロジックも逆によくわからないですね
14:32
あ、いや、いいのか
14:33
COW自体はシングルスレッドでも効果があるから。
Avatar
koher 20-Jul-17 02:33 PM
シングルスレッド前提なら同期コストがいらなかったけど、スレッドセーフにしようとすると同期コストがネックになるって話じゃないかな?
Avatar
omochimetaru 20-Jul-17 02:33 PM
あれ?でもマルチスレッドでもstd::string自体はreadonly thread safeなのであれば、COWを搭載する意味はあるような・・・
14:33
いや、ないのか
14:33
readonlyなときにはWがないから
Avatar
koher 20-Jul-17 02:34 PM
WがなくてもCOWじゃなかったらコピーが走っちゃうのでは?readonlyでも。
Avatar
omochimetaru 20-Jul-17 02:36 PM
あーそうか、readonlyでコピーするときに共有ですませるのがCOWの意義か
14:36
あーーわかったわかった
14:36
COWで共有したときは
14:36
std::string としては、2つに見えてるんだ。ユーザには。
14:37
でも、ユーザからしたら、 std::string 一個単位で readonly safe ってことしか聞いてないから (というかコピーをまたいだグループでロックを取るなんで不可能)
14:37
COWを意味のある形で実装するならスレッドセーフじゃないとだめか
Avatar
koher 20-Jul-17 02:38 PM
え?なんで?それってさっきの Array の COW はスレッドアンセーフでいい話と矛盾してない?
Avatar
omochimetaru 20-Jul-17 02:38 PM
SwiftのArrayの話のときそのパターン考えてなかった
Avatar
koher 20-Jul-17 02:38 PM
あー、そういうことか
Avatar
omochimetaru 20-Jul-17 02:39 PM
SwiftのArrayがコピーされるときは、そのとき内部でストレージへの参照がコピーされて、そのときそこだけatomicにちゃんと2になる
Avatar
koher 20-Jul-17 02:39 PM
var a = [2, 3, 5] // スレッドA a[2] = 4 // スレッドB var b = a b[2] = 999
14:39
みたいなときに、 ab で同期とるとか無理でしょってことか。
Avatar
omochimetaru 20-Jul-17 02:39 PM
そうそう
14:40
var a = [2, 3, 5] // スレッドA startThread { a[2] = 4 } // スレッドB startThread { var b = a b[2] = 999 }
Avatar
koher 20-Jul-17 02:40 PM
そうすると Array 自体はスレッドアンセーフでも COW はスレッドセーフでないといけないってこと?
Avatar
omochimetaru 20-Jul-17 02:41 PM
んー・・・? ↑のコードなら、 a[2] = 4var b = a の2行を、ユーザがロックすべきだと思う。
14:42
b = a の代入の最中に、 a[2] = 4 の処理が走り始めて内部状態が壊れる可能性があるはず。
14:42
じゃあstd::stringの話も一緒か。
14:43
C++11で a[2] = 4 が書き込み操作で、 b = a の右辺はreadだから、競合してるのでロックが要るって事になるはず (edited)
Avatar
koher 20-Jul-17 02:43 PM
そこが最初に考えてたところで、仮に COW の参照カウントチェックから変更までが atomic じゃないとして
Avatar
omochimetaru 20-Jul-17 02:43 PM
はい
Avatar
koher 20-Jul-17 02:43 PM
Array のスレッドアンセーフに関係ないところで
14:44
COW をぶっ壊して値型としての振る舞いを壊す例ってどういうのだろう?
14:45
Array はスレッドアンセーフなまま COW の部分だけスレッドセーフにして防げる事例。 (edited)
Avatar
omochimetaru 20-Jul-17 02:45 PM
ありえない気がするんだよなあ Arrayの内部ストレージに触れるのはArrayのメソッド実装部分だけだから
Avatar
koher 20-Jul-17 02:45 PM
それがないなら Array の COW はやっぱりスレッドアンセーフでいいということになるのかなぁ・・・。
14:45
話が堂々巡りしてる・・・
Avatar
koher 21-Jul-17 12:50 AM
昨日の↓これ本当? int の書き込みは atomic で同時なんてないんじゃないの?
Q4. 基本型intはスレッドセーフですか? A4. 「同時アクセスが全て読み込み操作であれば安全」というスレッドセーフ性レベルが保証される。
http://yohhoy.hatenablog.jp/entry/2013/12/15/204116
この記事はC++ Advent Calendar 2013の15日目にエントリしています。 内容はC++標準ライブラリとスレッドセーフに関する解説になります。 flickr / rennasverden もくじ What's スレッドセーフ? スレッドセーフという幻想 基本型とデータ競合 C++標準ライブラリとデータ競合 C++標準ライブラリ:シーケンスコンテナ編 C++標準ライブラリ:連想コンテナ編 スレッドセーフ RELOADED 基本的なスレッドセーフ保証 std::shared_ptr std::rand() std::cout (本文のみ約9000字) はじめに マルチスレッド…
Avatar
omochimetaru 21-Jul-17 12:51 AM
int一般がatomicなんて言ってないです
00:53
CPUにそういう機能があって
00:54
APIがあいてたり
00:54
I have googled for atomic increment and decrement operators on Mac OS X and found "OSAtomic.h", but it seems you can only use this in kernel space. Jeremy Friesner pointed me at a cross-platform a...
00:55
cppではさらにそれを標準化したりしてる
00:55
cppの方はCPUに機能が無ければロックになってる可能性もあるけど
Avatar
koher 21-Jul-17 12:56 AM
インクリメントは特殊な命令じゃないとatomicにならないのはわかるけど、ただの代入でもatomicになるとは限らない??
Avatar
omochimetaru 21-Jul-17 12:56 AM
もちろん
00:56
というかそうじゃなくて
00:56
命令が一単位かどうかは関係なくて
00:56
コンパイラがその理論的仮定に基づいた最適化をするんで (edited)
00:56
仮にCPUレベルで分解不能なコードであっても
00:57
マルチスレッドセーフにはならないです
00:57
順番入れ替え最適化があって
00:58
シングルスレッドなら最終的に同じ結果になるけど
00:58
コードの実行順が変わるとかあるので
Avatar
koher 21-Jul-17 01:05 AM
atomicだけどスレッドセーフでないと言っている?
01:05
それともintの代入自体がatomicであることも保証されていない?
Avatar
omochimetaru 21-Jul-17 01:11 AM
intへの代入のatomic性が保証されているかどうかは知らないです。 ただもしatomicだったとしても、複数のスレッドから同じ変数を見ていて、 ライターとリーダーがいるとき、 順序性の保証が無いから、だいたいバグるので、 なんらかの同期機構を使わずに生のintを共有すること自体がナンセンスだと言ってます (edited)
01:12
ただし昨日の話とも絡むけどリードオンリーなら生のintで共有しても大丈夫なはず。 (edited)
Avatar
koher 21-Jul-17 01:12 AM
ロックフリーのアルゴリズムとかってatomic性に依存してる気がするんだけど、順序が入れ替わることを考慮しても大丈夫なのかな?
Avatar
omochimetaru 21-Jul-17 01:13 AM
そのアトミックな命令に依存する箇所は順序性の保護が伝搬するはず
01:13
あーちょっとそこはわかんないな
01:14
でも、少なくともCAS命令の単位ではアトミックで
01:14
スレッド同士が同じところを見るのがCASだけになってれば
01:14
その前後は入れ替わってても、シングルスレッドの範疇で同じ結果に観測される
Avatar
koher 21-Jul-17 01:15 AM
CASでもインクリメントでも代入でも↓については同じ話じゃない?
命令が一単位かどうかは関係なくて
Avatar
omochimetaru 21-Jul-17 01:15 AM
同じ話じゃないです
01:15
えっとたしかに、代入だけを議論すれば
01:15
アトミックだったかもしれないけど
01:15
代入だけで役に立たないでしょう
01:15
そのあと読まないと。
01:16
もしくは、読んだ後に代入とか
01:16
なにかしら代入とはアトミック性が連結しない、その変数のリードや、他の変数のリードライトが
01:16
一緒に存在しないと、そのそもそもの代入を副作用とするロジックが書けない
Avatar
koher 21-Jul-17 01:17 AM
代入とreadがatomicだとして、元のブログの↓のコードはどんな問題が起こる?
// 同一変数に対して片方が変更操作 int y = 2; void th1() { int r2 = y; // NG: データ競合 } void th2() { y = 42; // NG: データ競合 }
Avatar
omochimetaru 21-Jul-17 01:19 AM
r2が2か42か不定ですね
01:19
この例だとグローバル変数だから無さそうだけど、例えば、th2の中身が丸ごと最適化で消えて、42の可能性が0%になる、とか、
Avatar
koher 21-Jul-17 01:20 AM
それはたとえ th1th2 の中でロックしてても不定じゃない?
Avatar
omochimetaru 21-Jul-17 01:20 AM
ちょっと書き加えていく仮定でどんどん変な事が起こり得る状態になります
01:20
ロックしてても不定だけど、
01:20
どっちになるか不定なコードとしてはそっちが正しい
Avatar
koher 21-Jul-17 01:22 AM
↓であったとしてもロックが必要ってこと?
struct Counter { var count = 0 mutating func countUp() { count += 1 } mutating func reset() { count = 0 } }
(edited)
01:22
あー、インクリメントは
01:22
atomic なインクリメントをするとして
Avatar
t.ae 21-Jul-17 01:23 AM
mutatingじゃないとじゃ
Avatar
koher 21-Jul-17 01:23 AM
ホントだ。修正しました。
Avatar
t.ae 21-Jul-17 01:24 AM
話よく分かってないですけどstructの場合CoWで実体分かれて問題ないんでは
Avatar
omochimetaru 21-Jul-17 01:24 AM
atomicなインクリメントと、生のリードを一緒に使っていいかはわかんないです
Avatar
koher 21-Jul-17 01:25 AM
readじゃなくてreset の write の方
Avatar
omochimetaru 21-Jul-17 01:25 AM
それもわかんないです。
01:26
同じ仲間の命令の書き込み命令を使うべきか、普通の書き込みと協調するのか知らないです
01:26
std::atomic<int>なら、リードもライトもインクリメントも専用メソッドがあるので
01:26
僕がcppで書くときはそこを気にしない
Avatar
koher 21-Jul-17 01:26 AM
@t.ae まず、 struct だからといって CoW は自動的には起こりません。
01:28
std::atomic<int>なら、リードもライトもインクリメントも専用メソッドがあるので
それはまた別の話じゃない?今atomicityを仮定しているので。
01:29
readもwriteもincrementも。
Avatar
omochimetaru 21-Jul-17 01:30 AM
全部仮定してるならそのクラスは問題なさそうだけど
01:30
incrementメソッドが実質的に役に立たないと思う
Avatar
koher 21-Jul-17 01:30 AM
↓が問題なのは、readやwriteのatomicityが保証されてないからなのか、それとも「順序」の問題なのか。
// 同一変数に対して片方が変更操作 int y = 2; void th1() { int r2 = y; // NG: データ競合 } void th2() { y = 42; // NG: データ競合 }
Avatar
omochimetaru 21-Jul-17 01:31 AM
その結果を見ようとしてresetに割り込まれるかも。
01:32
外部で同期して同時にincrementしまくってから外部で同期したあとに読む、とかなら
01:32
意味あるか。
01:32
えーと
01:33
最大の問題は、規格上明確にデータ競合であることですね
01:33
データ競合→未定義動作→全て消していい
01:33
みたいな、全く斜め上の結果とか
01:34
ありえるかも。
01:34
てか実際そういう話があって江副さんのブログで読んだ事がある
Avatar
koher 21-Jul-17 01:35 AM
それって↑の代入やインクリメントの代わりに CAS でも同じことが言えて、ロックフリーなプログラムとか書けなくならない? (edited)
Avatar
omochimetaru 21-Jul-17 01:36 AM
少なくともCAS命令同士はデータ競合を起こさないので
01:36
同じ変数を読むスレッド、書くスレッド両方が、CASだけでアクセスすれば大丈夫です
01:36
読む方はCASだと困るか
01:37
まあそのCASと一緒にやっていいと規定された操作
Avatar
koher 21-Jul-17 01:37 AM
それだと、
int y = 2; void th1() { y = 99; } void th2() { y = 42; }
の代入が atomic なら↑も OK となりそうだけど・・・。
Avatar
omochimetaru 21-Jul-17 01:37 AM
アトミックな型はC++においてデータ競合の問題が発生しない唯一の型です。
って書いてあるし
01:38
それはデータ競合でヤバそう
01:38
たとえば
01:38
std::atomic<int>::load() と std::atomic<int>::compare_exchange_strong() を使って
01:38
プログラムをかけば
01:38
データ競合は起こらないからちゃんとロックフリーアルゴリズムがかけます
Avatar
koher 21-Jul-17 01:39 AM
代入自体が atomic でないってこと?
Avatar
omochimetaru 21-Jul-17 01:39 AM
話が2つあって
Avatar
koher 21-Jul-17 01:39 AM
疑問は二つで、 - C++ において int の代入は atomic なのか - atomic だと仮定して↑はスレッドセーフなのか
01:39
後者は成り立つ気がしてるんだけど。
Avatar
omochimetaru 21-Jul-17 01:41 AM
・実際のある特定のCPUにおいてある種の操作がCPU命令としてatomicかどうか ・そのようなCPU特性を前提に書いたC++コードがスレッドセーフかどうか
01:41
で、現実的には2の問題でだいたい壊滅する
01:41
でもそういう話がしたいわけじゃなさそうなので
01:41
そこを巻き戻すと
Avatar
koher 21-Jul-17 01:42 AM
あらゆるCPU命令を考えたら前者が成り立たないからスレッドセーフと言えないということでいいのかな?
Avatar
omochimetaru 21-Jul-17 01:42 AM
違います
01:42
仮にコンパイルターゲットが前者に一致して、うまくいきそうにみえても
01:42
「C++規格上で」やっちゃいけないことをやっている場合
01:43
積極的に破壊される可能性があります。
01:43
つまり、実際には、「C++規格」っていう実際のCPUとは関係ないルール(実際のCPUよりも厳しい)
01:43
のもとで正しいコードを書かないといけない。
Avatar
koher 21-Jul-17 01:43 AM
それはC++の規格上で int の代入がatomicでないから、ってことやんね?
Avatar
omochimetaru 21-Jul-17 01:43 AM
そこはまだまって
01:44
疑問は二つで、 - C++ において int の代入は atomic なのか - atomic だと仮定して↑はスレッドセーフなのか
01:44
「intの代入はatomicなのか」って質問がすごく難しくて
01:44
少なくとも
01:44
アトミックな型はC++においてデータ競合の問題が発生しない唯一の型です。つまり、あるスレッドがアトミックなオブジェクトに書き込んでいる間に他のスレッドがそれを読み込んだ時、その動作はうまく定義され、未定義動作とはなりません。
なので
01:44
C++規格上、intは、「同時に読み書きするとデータ競合を引き起こす型」なので
01:44
未定義動作とされて
01:44
ぶっ壊れる可能性がある
01:45
でもそれが
01:45
「atomicでない」
01:45
と言えるのかよくわからないです。
01:45
C++だとatomicにも4段階ぐらいのレベルがあって (edited)
01:47
(調べ中
Avatar
koher 21-Jul-17 01:48 AM
C++でなくて、intの読み書きがatomicであることが保証されている言語なら↑のコードも問題がないよね?
Avatar
omochimetaru 21-Jul-17 01:48 AM
以下の列挙値はatomic変数への操作に指定可能な順序付けの種類を表す。
https://cpprefjp.github.io/reference/atomic/memory_order.html
コンパイラに許可されている最適化の一つに、「プログラムの意味を変えない限りにおいて、メモリアクセスの順番を変えたり、省略したりしてもよい」というものがある。また、マルチコアCPUにおいては、あるCPUコアによるメモリアクセスの順序が他のコアからも同じように見えるとは限らない。このような挙動はマルチスレッドプログラミングにおいて問題になることがある。
01:48
これだ、なんか6通りぐらい概念があって
01:49
int にたいしてどれが適用されるかよくわからない。
01:49
- atomic だと仮定して↑はスレッドセーフなのか
で、これは、スレッドセーフだと思います。
01:49
ただもちろん
01:49
代入だけじゃなくて
01:49
リードも
01:49
その代入と対でみてアトミックならって話ですが。
Avatar
koher 21-Jul-17 01:49 AM
はい。そのつもりです。 < read も atomic (edited)
Avatar
omochimetaru 21-Jul-17 01:50 AM
それならこれ自体はある時刻でyが2か42か99のどれかになるプログラム。 どれになるかはわからないけど、安全にどれかにはなる (edited)
01:51
スレッド2つとも終了時点では42か99の2択。
Avatar
koher 21-Jul-17 01:52 AM
Java だと longdouble 以外のプリミティブや参照の読み書きは atomic っぽいから、 int を同時に読み書きすること自体には問題なさそう。
For the purposes of the Java programming language memory model, a single write to a non-volatile long or double value is treated as two separate writes: one to each 32-bit half. This can result in a situation where a thread sees the first 32 bits of a 64-bit value from one write, and the second 32 bits from another write. Writes and reads of volatile long and double values are always atomic. Writes to and reads of references are always atomic, regardless of whether they are implemented as 32-bit or 64-bit values.
http://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html
Avatar
koher 21-Jul-17 02:00 AM
int の読み書きが atomic かどうかを調べて atomic だと知って安心した記憶があるんだけど、 Java の話だったのかなぁ。その感覚で int の読み書きを atomic だと思っていたから↓がおかしいんじゃないかと思ったけど、
// 同一変数に対して片方が変更操作 int y = 2; void th1() { int r2 = y; // NG: データ競合 } void th2() { y = 42; // NG: データ競合 }
C++ では規格上 atomic でないからたとえそれを atomic に行う CPU 向けにコンパイルしたとしてもどのように最適化されるかわからず未定義動作なので↑は正しい、と。
Avatar
omochimetaru 21-Jul-17 02:01 AM
はい。C++の話をするなら、「規格上atomicでないからどのようになるかわからないからバグ」は結構大事です、素朴な知識だと踏み抜くので
Avatar
koher 21-Jul-17 02:02 AM
Swift はどうなってるんだろう?
Avatar
omochimetaru 21-Jul-17 02:02 AM
例のごとく規定されてないのでは・・・
😂 1
Avatar
koher 21-Jul-17 02:02 AM
少なくとも参照カウントは atomic にインクリメント/デクリメントされてるだろうけど。
Avatar
omochimetaru 21-Jul-17 02:03 AM
それはそうで、内部をみたときに、Atomicなんたらとか使われてた。
02:04
問題はSwiftのコードとして、
var a = 3 var b = 2 a = 4 b = 1 print("a=\(a), b=\(b)")
(edited)
02:05
とかなってたときに、 a= 3, b = 2, a = 4, b = 1 って順序で必ず変化するか、代入がatomicか、などが不明ってことですね
Avatar
koher 21-Jul-17 02:05 AM
Int 等の代入や、参照型のアドレスの代入が atomic なのか気になる。
Avatar
omochimetaru 21-Jul-17 02:05 AM
実際、 a = 3b = 2 の時間帯は削除されるんじゃないかなあ。
Avatar
koher 21-Jul-17 02:06 AM
アドレスの代入が atomic じゃなかったらヤバイ動作しそうだな・・・
Avatar
omochimetaru 21-Jul-17 02:06 AM
LLVMのオプティマイザが賢そうなので。
Avatar
koher 21-Jul-17 02:07 AM
同時に代入したらアドレスの上位4バイトと下位4バイトが合成されたものができあがったとか・・・
Avatar
omochimetaru 21-Jul-17 02:07 AM
そうですねえ。まあ、実際64bit CPUならそういうのは大丈夫そうですが。
02:08
個人的には
02:08
実際c++と同程度に過激な最適化が
02:08
されるんじゃないかと思ってる
02:08
UnsafePointer<T>のヤバイ話とか見ても(前削除されたAPI
02:08
LLVMから先で同じ事やってそう
Avatar
koher 21-Jul-17 02:08 AM
Int やアドレスの代入が atomic でないなら、結構気を付けてプログラム書かないといけないなぁ
02:15
Swift Programming Language を "atomic" で検索してみたけど何もなかった。
Avatar
omochimetaru 21-Jul-17 02:16 AM
02:17
わざわざこれをやってるということは Int の read / write ですら atomic ではない?
Avatar
omochimetaru 21-Jul-17 02:17 AM
あ、これ .swift か。
02:18
これがあるってことはそんな感じがしますね > ただの Int じゃ駄目 (edited)
02:18
あ、あと、普通の変数って、 Int であっても
02:18
メモリ上の8バイトの値と
02:19
CPUで計算する前にレジスタにコピーして
Avatar
koher 21-Jul-17 02:19 AM
↓できた。
let a = _stdlib_AtomicInt(42)
Avatar
omochimetaru 21-Jul-17 02:19 AM
レジスタで計算してからメモリに書き戻したりするので
02:19
で、関数のコンパイル時にローカル変数とかをできるだけレジスタで済ませようとしたりするので
02:19
「Intの代入がatomic」だとしても
02:19
なんかもっと計算手順とかの関係で
02:19
競合が起きるシナリオとかがあるかもしれない。
Avatar
koher 21-Jul-17 02:20 AM
let a = _stdlib_AtomicInt(42) print(a.load()) // 42 a.store(999) print(a.load()) // 999
Avatar
omochimetaru 21-Jul-17 02:20 AM
少なくともレジスタで弄ってる間、メモリの値を他のスレッドからみたら、何の変化も起きてない、とかがあるし。
Avatar
koher 21-Jul-17 02:22 AM
C++ の std::atomic とか↑の _stdlib_AtomicInt とかも atomic であるところまでの保証であって「「Intの代入がatomic」だとしても」は同じじゃないの?
Avatar
omochimetaru 21-Jul-17 02:24 AM
あー 違う意味で使ってた
02:24
例えば
02:24
var x = 3 x = 2
02:24
こういうコードがあったとして
02:25
func a() -> Int { var a = 3 a = 2 return a }
02:25
上で「Intの代入がatomic」って言ったのは、「 Int に代入するとき、その操作がCPUにおいて不可分」
02:25
って事ですけど
02:25
func a の例で言うなら、これって
02:26
func a() -> Int { return 2 }
と最適化されるかもしれない
02:26
あーこれだとスレッド間共有が不可能だから微妙だな
02:26
func a(x: inout Int) -> Int { x = 3 x = 2 return x }
(edited)
02:26
これで。
02:27
で、これが、1スレッドだけ考えれば
func a(x: inout Int) -> Int { return 2 }
(edited)
02:27
に最適化される可能性があると思ってて
02:27
その場合
02:27
aが3になる時間や、2になる時間はなくなる。
02:27
でも、 std::atomic<int> に対しては
Avatar
koher 21-Jul-17 02:27 AM
a はどこから来たの?
Avatar
omochimetaru 21-Jul-17 02:27 AM
このような store 命令の削除も禁止されるはず。
Avatar
koher 21-Jul-17 02:27 AM
引数の xa の間違い??
Avatar
omochimetaru 21-Jul-17 02:28 AM
間違えた
02:28
@koher が最初から話してる「atomic」は
Avatar
koher 21-Jul-17 02:28 AM
もし xa だったら inout だから x への代入は必須じゃない?
Avatar
omochimetaru 21-Jul-17 02:28 AM
「その操作がCPUにおいて不可分」のことを指してると思ってるので。
02:29
あーじゃあ
02:29
func a(x: inout Int) -> Int { x = 2 return 2 }
(edited)
02:29
こうですね。
02:29
またまちがえた
02:29
x = 3 の瞬間が削除されていることと
02:29
return x じゃなくて return 2 になっていることがポイント
02:30
マルチスレッドでみると、 x=3 が観測できないし、 どんだけ x に書き込んでも、 固定で 2 が返ってくる
02:31
たとえば、別のスレッドで、「読み取った瞬間に3ならあたり、2ならハズレ」みたいなくじ引きロジックを実装していた場合
02:31
x = 3 が削除されるのは問題になりうる。
Avatar
koher 21-Jul-17 02:31 AM
うーん・・・
02:31
それは atomic でない a が atomic な挙動をしているだけだと思うんだけど、 (edited)
02:31
それは問題ないんじゃないかな?
Avatar
omochimetaru 21-Jul-17 02:33 AM
そうですかねえ
02:33
この記事に出てくる
02:33
int data = 0; volatile int flag = 0; // 生産側スレッド void producer_thread() { data = 42; // [A] flag = 1; // [B] ??? } // 消費側スレッド void consumer_thread() { while ( !flag ) {} // [C] assert(data == 42); // [D] ??? }
(edited)
02:34
みたいな例とかは
02:34
わりとやっちゃう気がしますけど
02:35
「代入がatomicだから」とかで自分で考えてスレッド同期しようとすると。
Avatar
koher 21-Jul-17 02:35 AM
↑は A と B が最適化で順序が入れ替わるかもしれないってこと?
Avatar
omochimetaru 21-Jul-17 02:37 AM
実行順[A], [B]、実行順[B], [A]の両者とも同じ結果をもたらすため、実行順の入れ替えが生じうる。同様の観点で、コンパイラは[C]と[D]の実行順も入れ替え可能であると判断する。
02:37
[C] と [D] が入れ替わるから、いきなりassertでコケて死ぬ
Avatar
koher 21-Jul-17 02:38 AM
言いたいのは、
func a() { lock.sync { atomicFoo(42) } } func b() { lock.sync { atomicFoo(999) } }
lock はいらないよね?ということで
Avatar
omochimetaru 21-Jul-17 02:38 AM
[a] と [b] が入れ替わることで、 [c] をすりぬけて [d]で死ぬってのもありますね
Avatar
koher 21-Jul-17 02:38 AM
↑の [A] と [B] はそもそも atomic じゃないからなぁ。
Avatar
omochimetaru 21-Jul-17 02:40 AM
仮に @koher のいう、「代入がatomic」だったとしても 入れ替えの問題は起きるのでは (edited)
02:41
つまり、 data を読んだ時に、0か42以外の中途半端にビットが書き換わった変な数字になったり、CPUがぶっ壊れたりしない、としても
02:42
Int やアドレスの代入が atomic でないなら、結構気を付けてプログラム書かないといけないなぁ
02:42
この発言のレベルだと、
02:42
かりに、「Intへの代入がatomicだったとしても」
02:43
↑の順序入れ替えとかに起因するバグを避けるのは難しいのではってことです
02:43
func a() { lock.sync { atomicFoo(42) } } func b() { lock.sync { atomicFoo(999) } }
これ自体はlockはいらない。
Avatar
koher 21-Jul-17 02:44 AM
はい、複数の命令で同期をとるのは当然として
02:45
Int を同時に更新する(だけ)みたいなのでも同期が必要となると想定していないケースが多そうということです。
02:48
つまり、↓の lock が不要だったらうれしい。
var x: Int = 42 func a() { lock.sync { x = 999 } } func b() { lock.sync { x = 888 } }
(edited)
Avatar
omochimetaru 21-Jul-17 02:50 AM
それは必要な気がする。文書上の根拠は無いけど、LLVMのオプティマイザを使うところで、C++並のアグレッシブな事がおきて、データ競合とみなされる可能性がありそう。
Avatar
koher 21-Jul-17 02:51 AM
うん、それが
Int やアドレスの代入が atomic でないなら、結構気を付けてプログラム書かないといけないなぁ
という気持ちです。
Avatar
omochimetaru 21-Jul-17 02:51 AM
LLVMアーキテクチャだと、そういうデータ依存関係の解析はLLVM-IRの上で行われるけど、それをやるかどうかは、コンパイラフロントエンドを実装する時に選択的に適用できるので
02:51
やる余地はあるけど、Swiftコンパイラが選択的に適用している/していない どちらもありえる。
02:52
なるほど > 気持ち
Avatar
rintaro 21-Jul-17 03:08 AM
結局のところ Swift4 の Existential CoW はヒープに 25 バイト以上のデカい構造体を alloc/initialize/dealloc するより参照カウンタ操作の方が速いってだけなのかな?
Avatar
koher 21-Jul-17 03:10 AM
代入時に不要なコピーをしなくていいところが大きいんじゃないでしょうか?
Avatar
omochimetaru 21-Jul-17 03:11 AM
alloc/initialize/dealloc
initializeがアロケートしたメモリにコピーを焼き込む操作なので
03:11
同じことを言っていますね
03:11
initialize が 不要なコピーのこと。
Avatar
rintaro 21-Jul-17 03:12 AM
Swift3 のときは、Existential のヒープストレージには参照カウンタついてなかったのだろうか?
Avatar
omochimetaru 21-Jul-17 03:13 AM
僕が調べたときにはそれらしいことは無かったですよ
03:13
Swift2かもしれないけど
03:13
Existentialがコピーされるたびに、alloc/init されてた
03:13
というか、24バイト以下の場合とほぼおなじで、それがその場のメモリか、用意したヒープか、みたいな。
03:14
Existential自体がヒープ上に追加領域をもつ可変長データ構造、みたいなイメージです
Avatar
rintaro 21-Jul-17 03:14 AM
では Exsitential 自体のメモリ使用量は参照カウンタの分増えたってことなんですね。
Avatar
omochimetaru 21-Jul-17 03:14 AM
そうですね。Existential1個で見ると増えると思います。
03:14
1回でもコピーして共有が生成されれば、25バイト以上あるときのはなしだから、 (edited)
03:15
25 - 8で17バイト以上得しそう
Avatar
rintaro 21-Jul-17 03:24 AM
大きい構造体をfunc間で取り回すときに、Exsitential に入れて取り回したほうが速い可能性を考えています。
Avatar
omochimetaru 21-Jul-17 03:26 AM
あ〜そうか・・・
03:27
いや!
03:27
クロージャでキャプチャしている場合は
03:27
そのクロージャがキャプチャするスコープのオブジェクトがヒープにできていて
03:29
一緒にキャプチャしている同士ではただのヒープの共有だから
03:29
あ、「func間で取り回すとき」って単に関数に引数として渡すとかも考慮しているんですかね。 (edited)
Avatar
koher 21-Jul-17 03:30 AM
引数として渡すならCOWの方がコピーが発生しなくて速いんじゃないですか?
Avatar
omochimetaru 21-Jul-17 03:30 AM
let x = LargeSizeValue() f1(x) f2(x) f3(x)
03:30
呼び出しのたびにコピーが生じるから、これがExistential渡しのほうが速いことがありそうだ
Avatar
koher 21-Jul-17 03:31 AM
あー、引数は必ず let だからそのまま渡せるのか
Avatar
omochimetaru 21-Jul-17 03:31 AM
いや、スタック上にコピーすると思います
Avatar
koher 21-Jul-17 03:32 AM
コピーするのは Existential への参照?
Avatar
rintaro 21-Jul-17 03:32 AM
func consume1(_ b: BigStruct) { consume2(b) } func consume2(_ b: BigStruct) { consume3(b) } func consume3(_ b: BigStruct) { consume4(b) } func consume4(_ b: BigStruct) { print(b) }
極端だけどこういう場合。
(edited)
Avatar
omochimetaru 21-Jul-17 03:33 AM
コピーするのは Existential への参照?
BigStructが関数呼び出しのたびにスタックにコピーされると思う
03:34
@rintaro そのコードならExistential化されてるとCOWが効いて早くなりそうに思います (edited)
Avatar
koher 21-Jul-17 03:34 AM
今プロトコル型で受けるときの話じゃないの?
Avatar
rintaro 21-Jul-17 03:34 AM
func consume1(_ b: P) { consume2(b) } func consume2(_ b: P) { consume3(b) } func consume3(_ b: P) { consume4(b) } func consume4(_ b: P) { print(b) } extension BigStruct: P {}
こうしたほうが速そう。
Avatar
omochimetaru 21-Jul-17 03:34 AM
@koher はい、そうです、だから前提として遅いパターンを考えています
Avatar
koher 21-Jul-17 03:34 AM
COW があるとき( Swift 4 )とないとき (Swift 3 )での比較をしているわけではない?
Avatar
omochimetaru 21-Jul-17 03:34 AM
@rintaro が言っているのは
03:34
Swift3/4の比較じゃなくて
03:34
Swift4において
03:35
「あえて」Exitentialで渡されるトリッキーな書き方をすると
03:35
動作速度で有利になるっていう変なことがおきるのでは、ってことだと思います
Avatar
koher 21-Jul-17 03:35 AM
結局のところ Swift4 の Existential CoW はヒープに 25 バイト以上のデカい構造体を alloc/initialize/dealloc するより参照カウンタ操作の方が速いってだけなのかな?
は Swift 3 vs Swift 4 の話ではない??
Avatar
omochimetaru 21-Jul-17 03:35 AM
それは3 vs 4の話ですね
Avatar
koher 21-Jul-17 03:36 AM
あれ?途中で話が変わってたのか
Avatar
omochimetaru 21-Jul-17 03:36 AM
@rintaro でも、結局それって、最適化で BigStructに特殊化された版になってしまいそう。
Avatar
rintaro 21-Jul-17 03:36 AM
はい、話かわってます😅
Avatar
koher 21-Jul-17 03:36 AM
おお、なるほど、話が続いてると勘違いしてた・・・
Avatar
omochimetaru 21-Jul-17 03:37 AM
(僕の中ではつながって聞こえてるけど・・・
Avatar
koher 21-Jul-17 03:37 AM
最適化で BigStructに特殊化された版
プロトコル型で受けてても specialize ってされるのかな?
Avatar
omochimetaru 21-Jul-17 03:37 AM
されますよ
03:38
ジェネリックじゃなくてプロトコル型で受けられるのは、associated typeが無い時だから
Avatar
koher 21-Jul-17 03:38 AM
↓でないとスペシャライズされないと思ってた。
func consume1<T: P>(_ b: T) { consume2(b) } func consume2<T: P>(_ b: T) { consume3(b) } func consume3<T: P>(_ b: T) { consume4(b) } func consume4<T: P>(_ b: T) { print(b) } extension BigStruct: P {}
Avatar
omochimetaru 21-Jul-17 03:40 AM
http://qiita.com/omochimetaru/items/b41e7699ea25a324aefa
// 1.swift protocol Hogeable { func hoge() -> Int } struct HogeCat: Hogeable { func hoge() -> Int { return 1111 } } func callHogeableHoge(hogeable: Hogeable) -> Int { return hogeable.hoge() } func callCatHoge(cat: HogeCat) -> Int { return callHogeableHoge(cat) } print(callCatHoge(HogeCat()))
# 導入 Swiftでは通常のプロトコルは変数の型として使用することができますが、 型パラメータ(associated type)を持つジェネリックなプロトコルの変数は作れません。 非ジェネリックな例 ```swift prot...
03:40
callHogeableHoge no
Avatar
koher 21-Jul-17 03:40 AM
↓のようになるってこと?
func foo(_ a: P, _ b: P) { ... } extension Int: P {} extension String: P {} foo(2, 3) // スペシャライズされる foo(2, "abc") // スペシャライズされない
Avatar
omochimetaru 21-Jul-17 03:40 AM
のときも特殊化された気がするけど自信なくなってきた
03:40
それは両方されそう
03:40
foo(Int, Int) と foo (Int, STring) が生成される
03:41
すぐ試せるから試すか
03:44
おや、されないな
Avatar
koher 21-Jul-17 03:45 AM
どっちも?
03:46
1個の場合もやってみる
Avatar
koher 21-Jul-17 03:46 AM
ジェネリックの場合も試してみないといけないかも。
03:47
ってか、 @_specialize 付けなくてもスペシャライズって起こるんだっけ?
03:47
ああ
03:47
同一モジュールなら
03:47
いいのか。
03:48
更新した
03:48
@koher があってた
03:48
ジェネリック関数の形式でかいたやつしか特殊化されなかった。 (edited)
Avatar
koher 21-Jul-17 03:48 AM
お、よかった。明日の発表を修正しなくて済んだw
Avatar
omochimetaru 21-Jul-17 03:49 AM
@rintaro
func consume1(_ b: P) { consume2(b) } func consume2(_ b: P) { consume3(b) } func consume3(_ b: P) { consume4(b) } func consume4(_ b: P) { print(b) } extension BigStruct: P {} こうしたほうが速そう。
↑これでいけそうです
Avatar
koher 21-Jul-17 03:50 AM
逆にジェネリックにしてしまうとスペシャライズされて遅くなると・・・
03:50
悲しい
Avatar
omochimetaru 21-Jul-17 03:50 AM
これでなおさらOwnershipが待ち遠しくなるな
03:50
shared渡しができるから
03:51
Existentialテクニックより早くできる
03:51
func consume1(_ b: shared BigStruct) { }
03:51
これでC++の void consume1(const BigStruct & b) と同じ意味
Avatar
koher 21-Jul-17 03:52 AM
今でも↓が最速?
func consume1(_ b: inout BigStruct) { consume2(&b) } func consume2(_ b: inout BigStruct) { consume3(&b) } func consume3(_ b: inout BigStruct) { consume4(&b) } func consume4(_ b: inout BigStruct) { print(b) } extension BigStruct: P {}
(edited)
03:52
ああ P じゃない→修正 (edited)
Avatar
omochimetaru 21-Jul-17 03:52 AM
あ、そうですね、それは速いです。
03:54
でも、こういうことができない
var x = BigStruct() compose(consume1(&x), consume1(&x))
03:54
Low of Exclusivity のおかげで、同時に writable 参照 を 2つ作ってはいけない
03:55
まあconsume1なら返り値が無いから↑のような例はありえないけど、仮に返り値があるとしたら、です。
Avatar
omochimetaru 21-Jul-17 04:31 AM
Swiftの参照カウンタは std::atomic で実現されてました。 struct HeapObject に フィールド InlineRefCounts refCounts がある。 https://github.com/apple/swift/blob/b7d78853112c1279fc7bc5b85853779040f13703/stdlib/public/SwiftShims/HeapObject.h InlineRefCounts は RefCounts<InlineRefCountBits> のエイリアス class RefCounts<T> は フィールド std::atomic<T> を持ってる。 デクリメント処理はなんかいろいろあるけど doDecrement が基本的なやつっぽくて、 分岐もいろいろ複雑なんだけどstd::atomicのcompare_exchange_weakを呼び出してたりする。 InlineRefCountBits は RefCountBitsT<RefCountIsInline> のエイリアス RefCountIsInline は true な定数 RefCountBitsTはカウンタに加えて動作に関するビットが5こぐらいくっついたよくわからんやつ。 https://github.com/apple/swift/blob/b7d78853112c1279fc7bc5b85853779040f13703/stdlib/public/SwiftShims/RefCount.h
swift - The Swift Programming Language
swift - The Swift Programming Language
Avatar
rintaro 21-Jul-17 04:57 AM
⚠️ DO NOT MERGE ⚠️ This is the bare minimum to get the frontend to accept shared and owned. @guaranteed semantics and inout-to-borrowed conversions are coming next.
Avatar
omochimetaru 21-Jul-17 04:58 AM
おお。 なんでアンスコついてるんだろう
Avatar
rintaro 21-Jul-17 04:59 AM
まだ evolution 通ってないからでしょうね。コメントで アンスコいらなくね?って言われてるけど。
Avatar
omochimetaru 21-Jul-17 05:00 AM
非公式だよ〜みたいな気持ちが込められてるってことですか
05:00
あーでもたしかに微妙にマージされて、その部分に興味ない人が、うっかり使ったりするとメンドイからそのほうがいい気もします
Avatar
koher 21-Jul-17 05:02 AM
ブランチ名が the-sharing-economy w
Avatar
omochimetaru 21-Jul-17 05:02 AM
Avatar
rintaro 21-Jul-17 05:03 AM
CodaFi のブランチ名はいっつもこんなですw
Avatar
koher 21-Jul-17 05:04 AM
いつもw
05:07
Gmail になってるけど Apple の人なの?
Swift Static Analysis@Apple Cupertino, CA
https://twitter.com/CodaFi_
Desktop developer. Programming language enthusiast. reenignE. 20. Aspiring Type Theorist. λΠω Lover. Math@CMU 2019. Swift Static Analysis@Apple
Tweets
9274
Followers
1432
05:08
Math@CMU 2019
どういうこと?未来人??
Avatar
omochimetaru 21-Jul-17 05:22 AM
2020年オリンピック出場予定とかそういうの?
Avatar
koher 21-Jul-17 05:23 AM
CMUってカーネギーメロン大学だと思うんだけど、2019年に数学科を卒業ってこと??学生でインターン?
Avatar
rintaro 21-Jul-17 06:11 AM
インターン2回目中だったような。去年もインターンやってた。
06:13
けどもう apple.com のメールアドレスで活動しているから、中の人になっているのかも。
06:19
https://swiftcoders.podbean.com/e/54-robert-widmman-swift-compiler-intern-swift-open-source-contributor/ 発見した。やっぱり今年もインターンみたいです。
Follow The SwiftCoder Journey at WWDC 2017 via Instagram. I'll be posting a lot of Stories: https://www.instagram.com/swiftcoders/ Come to The SwiftCoders Meet & Greet at AltConf 2017. Find all the details here: https://swiftcoders.eventfarm.com In thi...
👀 1
Avatar
koher 21-Jul-17 06:20 AM
インターンでSwiftコンパイラできるとかいい環境だなぁ。
Avatar
omochimetaru 31-Jul-17 03:22 AM
@omochimetaru @mitsuse_t letでも参照型だったらイミュータビリティを保証できないし、値型だったらreadonlyとの区別はないし、readonlyとimmutableという話とは違うんじゃないかな?それよりも参照型でイミュータブルを保証する言語機能がほしいと思ってたけど、値型中心ならいいやってなった。
03:22
@koher @mitsuse こっちで書くけど、 参照型であっても「同じインスタンスが毎回返る」事に意味はあると思う。
Avatar
koher 31-Jul-17 03:25 AM
たしかに?
03:26
Kotlin だと val ( Swift の let に相当)で interface のプロパティ宣言して、具象クラス側で Computed property にできるよね・・・。
03:27
やっぱり参照型は値を返すときに考えるべき概念が複雑過ぎる気がする。
03:28
単純に値を返すだけでも - 毎回同じインスタンスを返す - シャローコピーを返す - ディープコピーを返す に加えて、処理結果だと - 毎回処理を実行する - キャッシュを返す となって、後者がミュータブルだと↑の 3 通りがあり得る。
Avatar
omochimetaru 31-Jul-17 03:28 AM
はい。だからkotlinのinterfaceのvalは嫌い。
03:30
@koher そこらへんはプロジェクトやモジュール単位での規約付けと、場合によってはnaming conventionを持ち込むしかないですよね
Avatar
koher 31-Jul-17 03:30 AM
本当はそういうのを言語機能で区別して適切に制限を加えたりできるべきだと思うけど、初心者がその違いを常に意識するのはハードルが高いし、初心者でなくても厳密に区別できてないことは多そう・・・。
03:32
せめてイミュータブルな世界だけを分離できるように、 Swift 以前は↓みたいなのがいいんじゃないかと思ってた。 mutating を一つももたないクラスはイミュータブルクラスになる。
mutable class Foo { func bar() -> Bar {} mutating func baz() -> Baz {} }
(edited)
03:32
イミュータブルクラスに mutating を作ろうとするとコンパイルエラー。
03:33
↑ができるとコンパイラや処理系がイミュータブルな範囲を認識できるようになって、遅延評価とかもできるようになる。
Avatar
omochimetaru 31-Jul-17 03:33 AM
C++のconst仕様をデフォルト逆側でやるかんじかな
03:34
Swiftのstrcut func のmutating みたいに、C++はメソッドに const をつけられて、constなメソッドの中からはconstなメソッドしか呼べないし、 const T な型にたいしてはconstはメソッドしか呼べないから、 constな範囲を連鎖的に保証する
Avatar
koher 31-Jul-17 03:34 AM
だから最初 Swift の mutating みたときは、これはもしかして?と思ったけどちょっと違った。けど、結局値型中心で考える方がセンスがいいと思う。
Avatar
omochimetaru 31-Jul-17 03:35 AM
Swiftのmutatingは struct ツリーにおいて同じように働くけど class 周りはそういうのは無いですね
03:46
これかな?
03:46
pure funcの話
Avatar
omochimetaru 31-Jul-17 03:48 AM
let フィールドだけなら 引数のない純粋関数として一般化できるのか。
Avatar
koher 31-Jul-17 03:49 AM
↑ D 言語のpure について言及されてて、 D 言語はよく知らないですが、、 pure な方がデフォルトであるのがいいと思うのと、これを型にも広げられないんだったら効果半減だと思います。
Avatar
omochimetaru 31-Jul-17 03:49 AM
あ〜そうか〜・・・ もし let なフィールドを許すとなると
03:50
じゃあ、 get / set できて getter/ setter のアクセサがついてない、stored propertyである制約が欲しい (edited)
03:50
とかもでてきちゃって
03:50
でもSwiftだと、 stored property が いつのまにか computed property にかわっていたとしても (edited)
03:50
呼び出し側に影響を与えないっていうのがこれまでの実態で
03:51
let フィールドに関しても同じで、 もともと let な stored property だったものを、後から computed property の getter に差し替えても 呼び出し側はそのままのコードでコンパイルできるわけだから
03:51
protocol だけ、そこが変更に敏感な仕様が入るのは不自然な場面が出てきそう
03:55
いや、let から var get になる分には緩める側だから問題ないかな・・・?
Avatar
koher 31-Jul-17 03:55 AM
うーん、 let なプロパティを Computed Property としてオーバーライドできないという制約はあるから、「もともと let な stored property だったものを、後から computed property の getter に差し替えても」動くとはいえ意図的に区別して制約が課されてるんじゃないかな?
Avatar
omochimetaru 31-Jul-17 03:56 AM
書き換えじゃなくてオーバーライドで考えるとたしかに。
Avatar
mitsuse 31-Jul-17 04:48 AM
Kotlin だと val ( Swift の let に相当)で interface のプロパティ宣言して、具象クラス側で Computed property にできるよね・・・。
なるほど Kotlin 書いたことないのですが, こういうのがかけてしまうんですね... (これは嬉しくなさそう...)
interface A { val value: Int } class A1: A { override val value: Int get() = A1.getCurrent() companion object { var value: Int = 0 fun getCurrent(): Int { value += 1 return value } } } fun main(args : Array<String>) { val a1 = A1() println(a1.value) println(a1.value) }
Avatar
norio_nomura 31-Jul-17 04:51 AM
Avatar
omochimetaru 31-Jul-17 05:18 AM
@mitsuse そうなんですよね
05:21
@norio_nomura この話題っぽいですね
Avatar
norio_nomura 31-Jul-17 05:22 AM
スレッドを読んだ限り、initializer内でどう扱うか?に問題があるぽい。
Avatar
koher 09-Aug-17 03:14 AM
protocol で nested type 作れないのって何か理由があるんですっけ?名前空間的に、その protocol でしか使わない型をネストしたい・・・。
Avatar
omochimetaru 09-Aug-17 03:15 AM
protocolの内側に型を定義する話ですか?
Avatar
koher 09-Aug-17 03:15 AM
はい
Avatar
omochimetaru 09-Aug-17 03:15 AM
それともstructの内側にprotocolを定義する話?
03:15
明確な1次情報は見つかってないけど、以前話題に出て
03:15
もしそれができると
Avatar
koher 09-Aug-17 03:15 AM
protocol Foo { var bar: Bar { get } struct Bar { ... } }
みたいな
(edited)
Avatar
omochimetaru 09-Aug-17 03:15 AM
nested typeを持つことを型の制約として表明するようにも見えて
03:15
微妙そう。
03:16
たとえば protocol の内側に static func をかいたとき、それは、 Foo.hoge() と呼び出せるわけじゃなくて
03:16
Fooを満たす型が static func hoge を持たねばならない、っていう "制約" なので
03:17
Fooを満たす型が struct Bar を持たなきゃならない、みたいに見える
03:17
構文としては存在しないんで決めの問題ですけど。
Avatar
tarunon 09-Aug-17 03:18 AM
実質的にはassociatedtypeと同じなのでは
03:18
エイリアス貼るのか実装を持つのかの差はあれど、動きを見た時にそこまで大きく変わるようには思えない
Avatar
omochimetaru 09-Aug-17 03:18 AM
@tarunon associated type は、絞込条件として protocol をさらに付与できるけど、 struct の形式だからどうだろうね
Avatar
tarunon 09-Aug-17 03:18 AM
structに限定したいという意図があるのか (edited)
Avatar
koher 09-Aug-17 03:19 AM
はい。 Foo に関連したいくつかのパラメータをまとめた Bar を作りたいけど、 BarFoo から独立したら意味を持たない型なのでネストしたいって感じです。
Avatar
tarunon 09-Aug-17 03:20 AM
外側にstruct Bar<F: Foo> を作るのが筋良さそう
Avatar
t.ae 09-Aug-17 03:20 AM
protocol Foo { typealias Bar = FooBar var a: Bar { get } } struct FooBar { } struct FooImpl: Foo { var a: Foo.Bar }
Avatar
koher 09-Aug-17 03:20 AM
うーん、それだと Foo の異なる具象型間で Bar をやりとりできないですよね?
Avatar
t.ae 09-Aug-17 03:20 AM
解決はしてない
Avatar
koher 09-Aug-17 03:21 AM
@t.ae それは少し考えたけど、 _FooBar にしておけばありかもしれないなぁ。
Avatar
omochimetaru 09-Aug-17 03:22 AM
うーん、それだと Foo の異なる具象型間で Bar をやりとりできないですよね?
その型ってやっぱり普通に可視なんじゃないですかね
Avatar
tarunon 09-Aug-17 03:22 AM
Fooに型パラが特になければ、別にBar<F:Foo>じゃなくて、initにFooを渡すだけでも良いはず
Avatar
omochimetaru 09-Aug-17 03:22 AM
プロトコル固有の型、とかではなくて、名前がつけられれないですか?
Avatar
koher 09-Aug-17 03:23 AM
ダメだった・・・
1> protocol Foo { 2. typealias Bar = FooBar 3. var a: Bar { get } 4. } 5. 6. struct FooBar { 7. 8. } 9> let bar: Foo.Bar = Foo.Bar() error: repl.swift:9:27: error: cannot call value of non-function type 'Foo.Bar' (aka 'FooBar') let bar: Foo.Bar = Foo.Bar() ~~~~~~~^~
Avatar
t.ae 09-Aug-17 03:23 AM
作成ができないのか。
Avatar
omochimetaru 09-Aug-17 03:23 AM
Fooが具象化してない状態だとBarはエイリアス名で実際の型が不定でおかしそう?デフォルトの扱いがよくわからないけど
Avatar
koher 09-Aug-17 03:24 AM
typealias はデフォルトではないのでは?
Avatar
omochimetaru 09-Aug-17 03:24 AM
2. typealias Bar = FooBar
これ。
Avatar
koher 09-Aug-17 03:24 AM
associatedtype にしてデフォルト設定するんじゃないっけ?
Avatar
omochimetaru 09-Aug-17 03:25 AM
はい、なんで、 返り値の型とかで エイリアスのところから普通は推論されるけど、 その推論させるためのメソッドが全く定義されない場合に、 = で指定しておいた型になるんじゃなかったっけ
Avatar
tarunon 09-Aug-17 03:25 AM
Xcode9b5なら普通に通りますよ
Avatar
koher 09-Aug-17 03:26 AM
struct FooBar {} protocol Foo { associatedtype Bar } extension Foo { typealias Bar = FooBar }
Avatar
tarunon 09-Aug-17 03:26 AM
associatedtypeは不定になるから無理
Avatar
koher 09-Aug-17 03:27 AM
↑と
struct FooBar {} protocol Foo { typealias Bar = FooBar }
Avatar
omochimetaru 09-Aug-17 03:27 AM
あ、 associated type じゃなくて
03:27
ただのtypealiasか
Avatar
koher 09-Aug-17 03:27 AM
は別で、
03:27
多分 @omochimetaru が言ってたのは前者な気がする。
Avatar
omochimetaru 09-Aug-17 03:27 AM
そうですね、見間違えた
03:27
じゃあFoo自体はassociated typeを持っているわけではないのか
03:28
struct P0Param {} protocol P0 { typealias Param = P0Param var a: Param { get set } } var a = P0.Param() print(a)
03:28
うごきますね
Avatar
koher 09-Aug-17 03:28 AM
Xcode9b5なら普通に通りますよ
は、↓ですか?
1> protocol Foo { 2. typealias Bar = FooBar 3. var a: Bar { get } 4. } 5. 6. struct FooBar { 7. 8. } 9> let bar: Foo.Bar = Foo.Bar()
Avatar
omochimetaru 09-Aug-17 03:28 AM
Xcode9.0 beta5で動いた
Avatar
koher 09-Aug-17 03:28 AM
なるほど。
Avatar
omochimetaru 09-Aug-17 03:28 AM
protocolの中にtypealiasが書けるのはなぜなんだ・・・
03:29
実装上楽できるように?
03:29
本来はtypealiasの右辺にはジェネリックな型とassociated typeを組み合わせた式が来たりするのかな。 (edited)
Avatar
koher 09-Aug-17 03:29 AM
確かによく意味がわからないな < typealias in protocol
Avatar
omochimetaru 09-Aug-17 03:30 AM
まあ結果的に目的は果たせていますね・・・
03:30
struct in struct な nested struct とかも
03:30
同じ方式で
03:30
top level に名前持って定義させつつ、 typealias つかってnested name を別途与えることができそう。
03:31
そのほうがファイルがわけられていいな。
03:31
あ、outer struct に対する可視性が違うのか
Avatar
t.ae 09-Aug-17 03:32 AM
struct in structはextensionに定義できるのでファイル分けるのはできますね
Avatar
omochimetaru 09-Aug-17 03:33 AM
stored propertyが出せない
Avatar
norio_nomura 09-Aug-17 07:27 AM
Xcode 9 beta 4まではswift-4.0-branch-07-11-2017 https://github.com/apple/swift/tree/swift-4.0-branch-07-11-2017 みたいなブランチからビルドされてたぽいだけど、beta 5はどこからビルドされているのだろう? (edited)
swift - The Swift Programming Language
Avatar
omochimetaru 09-Aug-17 07:36 AM
そう言えば今回はxcode前の @norio_nomura の予告が無かったですね
Avatar
norio_nomura 09-Aug-17 07:38 AM
お?予告?
Avatar
omochimetaru 09-Aug-17 07:43 AM
@norio_nomura が、 swift-4.0-branch-07-11-2017 みたいなスナップショットが出ると、discordで報告していて、
07:43
その3日後とかにxcode betaの新しいのが出るのがパターンになっていたので
07:43
xcode beta5 は急に来た感じがありました
Avatar
norio_nomura 09-Aug-17 07:53 AM
ああ、僕はXcodeリリースとは無関係に気になったスナップショットを書いてました。
Avatar
omochimetaru 09-Aug-17 07:54 AM
無関係に書いてたけどたまたまそうなってたので、ってことです
Avatar
norio_nomura 09-Aug-17 07:55 AM
とりあえず挙動を確認したところ、 swift-4.0-DEVELOPMENT-SNAPSHOT-2017-08-02-a以降 swift-4.0-DEVELOPMENT-SNAPSHOT-2017-08-04-aより前 ぽい。 (edited)
Avatar
koher 09-Aug-17 11:39 PM
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
❣ 1
Avatar
tarunon 10-Aug-17 03:05 AM
enumも自動生成してくれるのか。通って欲しいな
Avatar
omochimetaru 10-Aug-17 03:05 AM
お、いいですね〜
Avatar
tarunon 16-Aug-17 09:23 AM
↑レビュー期間終わったけどどうなったやろか
Avatar
tarunon 16-Aug-17 11:22 PM
Acceptedだ。やった。
😍 3
🙂 1
22:31
async/awaitとactorだ
Avatar
norio_nomura 17-Aug-17 11:53 PM
This implements parsing and semantic analysis support for the async/await proposal that @jckarter and I are cooking. It doesn't include SILGen support yet, so it isn't ready for merging.
✨ 4
Avatar
koher 18-Aug-17 01:00 AM
Copy-On-Write (🐮) types like Array and String are sharable
リファレンスカウントとCOWはスレッドセーフだけど Array そのものの操作はスレッドセーフではない?
01:02
まだ出だしだけどこの Menifesto の英語すごく読みやすい。
Avatar
omochimetaru 18-Aug-17 01:02 AM
おおお、熱いのが来ましたね
Avatar
koher 18-Aug-17 01:02 AM
"Error Handling Rationale and Proposal" とは違う・・・。
Avatar
omochimetaru 18-Aug-17 01:02 AM
ラトナー、がっつりやってたのか
Avatar
koher 18-Aug-17 01:03 AM
例の async, await 出す前に来てしまった・・・。
Avatar
omochimetaru 18-Aug-17 01:03 AM
機械学習にお熱なのかと😂
Avatar
koher 18-Aug-17 01:04 AM
↓わかりやすい。
Concurrency is a broad and sweeping concept that can cover a wide range of topics. To help scope this down a bit, here are some non-goals for this proposal: - We are focusing on task based concurrency, not data parallelism. This is why we focus on GCD and threads as the baseline, while completely ignoring SIMD vectorization, data parallel for loops, etc. - In the systems programming context, it is important for Swift developers to have low-level opt-in access to something like the C or C++ memory consistency model. This is definitely interesting to push forward, but is orthogonal to this work. - We are not discussing APIs to improve existing concurrency patterns (e.g. atomic integers, better GCD APIs, etc).
Avatar
koher 18-Aug-17 01:17 AM
現状の非同期機構は辛すぎるから多くの API が同期の形で提供されている、という話の例として UIImage(named:) が挙げられてるんだけど、このレベルの API から非同期化するつもりなのかな? C# の世界みたいになりそう。
Avatar
tarunon 18-Aug-17 01:18 AM
根っこのmain関数がasyncならまあ成り立つしな…と言う気はする
01:19
でもそれならasync基本でsync修飾の方が良いのかな?
Avatar
koher 18-Aug-17 01:19 AM
それは同期で良いものまで非同期になっちゃうから、必要なときだけ async が良さそう。
01:19
デフォルト throws って言ってるのと同じ気がする。
Avatar
tarunon 18-Aug-17 01:21 AM
たしかに
Avatar
koher 18-Aug-17 01:27 AM
can of worms って出てきてなんだ?と思ったら↓のような意味の表現らしい。
複雑で解決困難な問題、ゴチャゴチャした状態
http://eow.alc.co.jp/search?q=%22can+of+worms%22
(edited)
can of worms 《a ~》複雑で解決困難な問題、ゴチャゴチャした状態・This proje... - アルクがお届けする進化するオンライン英和・和英辞書データベース。一般的な単語や連語から、イディオム、専門用語、スラングまで幅広く収録。
Avatar
omochimetaru 18-Aug-17 01:28 AM
can って缶のほうか
Avatar
koher 18-Aug-17 01:29 AM
多分
Avatar
omochimetaru 18-Aug-17 01:29 AM
Avatar
t.ae 18-Aug-17 01:30 AM
「釣り餌用の虫の入ったカン」のことで、それを開けると、虫がぞろぞろと出てくるので、すぐに蓋を閉めないと厄介なことになる。
Avatar
omochimetaru 18-Aug-17 01:30 AM
かん1 缶 a can a canister (お茶の葉などを入れる). 缶切り 《主に米国で用いられる》 a can opener 《主に英国で用いられる》 a tin opener. 缶ビール canned beer a can of beer (1 個).
01:30
缶って日本語だっけ英語だっけと思ったけどあった
Avatar
tarunon 18-Aug-17 01:31 AM
オランダ語由来っぽい
01:31
じゃあカステラとかと同じ時期かな?
Avatar
koher 18-Aug-17 01:31 AM
「缶」と「できる」の他の "can" があるのかどうかを知らないから、おそらく "can of worms" の "can" は「缶」だけど自身はない。
01:32
缶の漢字は当て字?
01:32
↑ can of wormsの画像検索
Avatar
tarunon 18-Aug-17 01:32 AM
デジタル大辞泉 - 缶/罐/鑵の用語解説 - 《〈英〉canまたは〈オランダ〉kanから。「缶」「罐」「鑵」は当て字》1 金属の薄い板で作った容器。特に、ブリキ製のものをいう。「石油―」2 「缶詰」の略。「鮭(さけ)―」
Avatar
omochimetaru 18-Aug-17 01:33 AM
オランダんだ
Avatar
tarunon 18-Aug-17 01:33 AM
日本古来のものは「ほとぎ」と言って
01:33
同様の目的のものがあって漢字はそこから転用したのかな
Avatar
omochimetaru 18-Aug-17 01:34 AM
やっとasyncのサンプルコードが出てきた
01:34
(上から読んでるナウ
Avatar
koher 18-Aug-17 01:35 AM
まだそこまで行ってない。速いね。
Avatar
hironytic 18-Aug-17 01:38 AM
あんまり低レベルなAPIをasyncにされると、それを使うものは基本みんなasyncにする必要が出てきて困った世界になりそうなんですが。<C#の世界をちら見しながら
Avatar
omochimetaru 18-Aug-17 01:38 AM
can of wormsとか無視してるんでw
😂 1
Avatar
tarunon 18-Aug-17 01:39 AM
try!よろしくawait!みたいなものがあれば、そこまで困らない気はしていて
01:39
時間のかかるAPIがそれと解って取り回しが聞いて、同期化も楽ならそれはそれで良さそう
Avatar
hironytic 18-Aug-17 01:41 AM
そういう世界に振ってしまうのなら、基本がasyncでasyncの記述はいらなくて、awaitの記述も不要で代わりにnowait(asyncでも待たない)がある世界でもいいのかなと思ってしまう
Avatar
tarunon 18-Aug-17 01:42 AM
基本非同期で成り立つ世界はそれはそれでアリだとは思うンですよね
01:42
まあ別言語でやった方が平和だとは思う
Avatar
hironytic 18-Aug-17 01:43 AM
それはそうですね。Swiftでやってほしくはないかも。
Avatar
koher 18-Aug-17 01:43 AM
UIImage(named:) にまで踏み込むなら、 pure Swift UI ライブラリもワンチャンあるかも?
Avatar
koher 18-Aug-17 01:52 AM
↓の🐟は何?🐮=COWはわかったけど。
you should only have to teach your types how to serialize/🐟 themselves
Avatar
omochimetaru 18-Aug-17 01:53 AM
それ謎だった
01:53
serialize/X だし deserializeかなあ?
🤔 1
01:54
A fish emoji, swimming in a non-tropical climate. Fish was approved as part of Unicode 6.0 in 2010 …
01:55
絵文字としては fish なんだよなあ
Avatar
koher 18-Aug-17 02:05 AM
お、 Unrecoverable なエラーからの回復の話をしてる。
Speaking of reliable systems, introducing an actor model is a good opportunity and excuse to introduce a mechanism for handling and partially recovering from runtime failures (like failed force-unwrap operations, out-of-bounds array accesses, etc). We explore several options that are possible to implement and make a recommendation that we think will be a good for for UI and server applications.
Avatar
koher 18-Aug-17 02:14 AM
やっと async / await まで来た。
Avatar
omochimetaru 18-Aug-17 02:15 AM
なんかそこ記述量がすごいすくなくて
02:15
throwsみたいな async と、呼び出しの await は
02:15
提示されてるけど
Avatar
omochimetaru 18-Aug-17 02:16 AM
それ以上の話は書いてない、もっと下の方に出てくるかもしれないけど Actor についての議論が長い。
Avatar
koher 18-Aug-17 02:16 AM
(Int) -> Int // #1: Normal function (Int) throws -> Int // #2: Throwing function (Int) async -> Int // #3: Asynchronous function (Int) async throws -> Int // #4: Asynchronous function, can also throw.
02:16
reasync がなさそうだから swift-evolution に書いておくか。
02:16
await! もほしいな。
02:17
でも ! を使うのが良いのか自信がない。
Avatar
tarunon 18-Aug-17 02:21 AM
議論の種になればそれで良いのでは
Avatar
omochimetaru 18-Aug-17 02:21 AM
ああ
02:22
async/awaitの詳細は、この、プロポーザル下書きのほうにかいてあるわ。
02:22
NOTE: This section is concrete enough to have a fully baked proposal.
02:22
1行目に書いてあった。
02:23
Part1がasync/await、Part2がactor
actor TableModel { let mainActor : TheMainActor var theList : [String] = [] { didSet { mainActor.updateTableView(theList) } } init(mainActor: TheMainActor) { self.mainActor = mainActor } // this checks to see if all the entries in the list are capitalized: // if so, it capitalize the string before returning it to encourage // capitalization consistency in the list. func prettify(_ x : String) -> String { // ... details omitted, it just pokes theList directly ... } actor func add(entry: String) { theList.append(prettify(entry)) } }
02:23
Part3はなんかアクターとエラーについての話、reliability
reliable actor Notifier { ... } reliable actor class Notifier { ... }
02:26
Part4がネットワーク越しのactorとかの話
distributed actor MyDistributedCache { ... } distributed actor class MyDistributedCache { ... }
Avatar
koher 18-Aug-17 02:30 AM
とりあえず reasync について送ってみた。 https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170814/038917.html
❣ 2
Avatar
omochimetaru 18-Aug-17 02:39 AM
async/awaitのためにcoroutineの概念を導入して、generatorとかも整理しようって話の流れKotlinで見たな。
Avatar
koher 18-Aug-17 02:42 AM
Kotlin が残念なのは typed & marked propagation がないからせっかく非同期整えたのに、エラー処理がザルなんだよなぁ。 (edited)
Avatar
omochimetaru 18-Aug-17 02:59 AM
func queueHopping() async -> Void { doSomeStuff() await DispatchQueue.main.syncCoroutine() doSomeStuffOnMainThread() await backgroundQueue.asyncCoroutine() doSomeStuffInBackground() }
Avatar
koher 18-Aug-17 02:59 AM
/// Begins an asynchronous coroutine, transferring control to `body` until it /// either suspends itself for the first time with `suspendAsync` or completes, /// at which point `beginAsync` returns. If the async process completes by /// throwing an error before suspending itself, `beginAsync` rethrows the error. func beginAsync(_ body: () async throws -> Void) rethrows -> Void
↑の戻り値ってなんで T じゃないの?
Avatar
omochimetaru 18-Aug-17 02:59 AM
おもしろい。 doSomeStuffOnMainThread() は メインスレで同期的に実行されて
03:00
doSomeStuffInBackground() はBGスレ
03:00
@koher それは、同期コンテキストから、非同期コンテキストを開始して、投げっぱなしにするやつです
03:00
@IBAction func buttonDidClick(sender:AnyObject) { // 1 beginAsync { // 2 let image = await processImage() imageView.image = image } // 3 }
Avatar
koher 18-Aug-17 03:01 AM
投げっぱなしだとこの rethrows はどこで活躍するの?
Avatar
omochimetaru 18-Aug-17 03:01 AM
一緒に書いてるコメントにかいてあるけど
03:01
beginAsyncで投げた処理が
03:02
最初のawaitに到達するまえに
03:02
例外を投げたときです
03:02
beginAsyncの呼び出し時点で並列化するんじゃなくて
03:02
beginASyncの出だしはbeginAsyncのcallerと同じスレッドで実行されて
03:02
beginAsyncの中でawaitとともにasyncな関数を呼ぶところで
03:03
beginAsyncがreturnするってかいてある
Avatar
koher 18-Aug-17 03:03 AM
ああ、ちゃんと読んでなかった。 (edited)
03:04
確かに書いてあった・・・
If the async process completes by throwing an error before suspending itself, `beginAsync` rethrows the error.
Avatar
omochimetaru 18-Aug-17 03:06 AM
そうですね。ちょうどIBActionの例なのも一緒。
Avatar
koher 18-Aug-17 03:11 AM
なんで suspendAsync
func suspendAsync<T>( _ body: (_ continuation: @escaping (T) throws -> ()) -> () ) async rethrows -> T
じゃないんだ??
03:11
そしたら二ついらなくない?
Avatar
omochimetaru 18-Aug-17 03:12 AM
ん?違いますよ
03:12
continuationは
03:12
bodyの引数なんで
03:13
suspendAsync自体の返り値をどうするかを決めるやつだから
03:13
continuationを呼び出すことが、suspendAsyncの返り値のTを送信する処理です
03:13
suspendAsync自体が失敗することを示すためには
03:13
そのためのerror-continuationが必要
03:13
↑のようなシグネチャの場合、「エラーだったよ」を送信できないです
03:14
むしろ、送信しようとするとエラーが返ってくる可能性があるっていう
03:14
よくわからないことになってる
Avatar
koher 18-Aug-17 03:14 AM
ああ、 throws の位置がおかしいか
Avatar
omochimetaru 18-Aug-17 03:14 AM
continuationの実体を実装するのはユーザーじゃないです。
03:14
ユーザーはconitnuationを呼び出すだけ。
Avatar
koher 18-Aug-17 03:14 AM
func suspendAsync<T>( _ body: (_ continuation: @escaping (T) -> ()) throws -> () ) async rethrows -> T
Avatar
omochimetaru 18-Aug-17 03:15 AM
それでもやっぱりだめで
03:15
bodyの中で非同期処理を発火したいから
03:15
body自体のthrowsで表していても
03:15
非同期処理が失敗するかどうかbodyでは待てない
03:15
あれです、これ、HTML5/JSのPromiseのコンストラクタと同じ。 (edited)
Avatar
koher 18-Aug-17 03:16 AM
うん、それはわかってるんだけど
Avatar
omochimetaru 18-Aug-17 03:16 AM
// Legacy callback-based API func getStuff(completion: (Stuff) -> Void) { ... } // Swift wrapper func getStuff() async -> Stuff { return await suspendAsync { continuation in getStuff(completion: continuation) } }
03:16
↑この例がわかりやすい
Avatar
koher 18-Aug-17 03:16 AM
asynchronize が間違ってるっぽいな。
Avatar
omochimetaru 18-Aug-17 03:16 AM
既存のコールバックベースのAPIを、suspendAsyncを使って、async/await化する例。
03:17
async化してるわけじゃないな・・・
03:17
asyncコンテキストの中から、既存のコールバックベースを呼び出す例でした。
03:17
まあ、その、呼び出す瞬間に、ローカルにasync/await化しているとも言える。 (edited)
Avatar
koher 18-Aug-17 03:18 AM
まあ名前は良くてやりたいことは同じそう。
Avatar
omochimetaru 18-Aug-17 03:19 AM
いや、 @koher のasynchronize は間違ってないと思う
03:19
クロージャーのネスト数が違ってて
03:20
あ、ちがうな
03:20
まって、カッコが多すぎて見えない
Avatar
koher 18-Aug-17 03:20 AM
func suspendAsync<T>( _ body: (_ continuation: @escaping (T) -> ()) -> ()) async -> T func asynchronize(_ operation: ((T) throws -> ()) -> ()) async rethrows -> T // ラベル等を消すと func suspendAsync<T>( _ body: ((T) -> ()) -> ()) async -> T
(edited)
Avatar
omochimetaru 18-Aug-17 03:21 AM
なんかへんですね、 (T) throws -> () があるけど、
03:21
() throws -> T じゃないと。
Avatar
koher 18-Aug-17 03:21 AM
throws は間違えてるね。
Avatar
omochimetaru 18-Aug-17 03:22 AM
その上でもういっこ包めば正しくなるかな?
Avatar
koher 18-Aug-17 03:22 AM
かも
03:25
↓ならいけるか?
func asynchronize(_ operation: ((() throws -> T) -> ()) -> ()) async rethrows -> T
Avatar
omochimetaru 18-Aug-17 03:25 AM
直感だけどそうw
03:25
T | error を送信する代わりに、 () throws -> Tを送信する
Avatar
koher 18-Aug-17 03:25 AM
だから、↓か。
func suspendAsync<T>( _ body: (_ continuation: @escaping (() throws -> T) -> ()) -> ()) async -> T
Avatar
omochimetaru 18-Aug-17 03:25 AM
Promiseモナドのclosureへのかきかえですね
03:26
ですね
03:26
でも個人的にはやっぱりクロージャーにしちゃうと型としては少しゆるくなってるんで
03:27
成功とエラーでそれぞれコールバックがある形がマシに思う
03:27
あと今あらためておもったけどネストカッコが多いと読みづらい。
Avatar
koher 18-Aug-17 03:28 AM
return await suspendAsync { continuation, error in awaiters.append({ switch $0 { case .error(let e): error(e) case .value(let v): continuation(v) } }) }
return await suspendAsync { continuation in awaiters.append({ switch $0 { case .error(let e): continuation { throw e } case .value(let v): continuation { v } } }) }
になる。
Avatar
omochimetaru 18-Aug-17 03:28 AM
ですね。
03:28
あれ?てかそこbreakいらんのか
03:28
関係ない話だけど。
Avatar
koher 18-Aug-17 03:28 AM
break は空のとき以外いらないはず。
03:29
Python の pass みたい。
Avatar
omochimetaru 18-Aug-17 03:29 AM
え!!!!!!!
03:29
あ〜〜〜〜〜〜^
03:29
書き始めると怒られるから最初にbreak書くから
03:29
全く気がついてなかったw
Avatar
koher 18-Aug-17 03:29 AM
まじすかw
Avatar
omochimetaru 18-Aug-17 03:29 AM
www
03:29
case書く、xcode赤くなる、break書く、本文書く
03:29
って誘導されてた
Avatar
omochimetaru 18-Aug-17 03:53 AM
async await じゃなくて yieldsyield にするって選択肢についても書かれてますね
03:53
非同期のための別スレへの投入とかはこの言語機能の外の話で、ものとしてはcoroutineにすぎないから、と。
Avatar
koher 18-Aug-17 03:54 AM
async / await は必ずしも意味が正しくないんよね。
03:54
asynchronous とは限らないし。
Avatar
omochimetaru 18-Aug-17 03:55 AM
async, throwsの直交をやめて、asyncならthrowsであることにするとシンプルだよねって話もでてきた
Avatar
koher 18-Aug-17 03:55 AM
うん、でもそれは微妙だと思う。
03:55
すでに失敗しない前提の非同期 API とかあるし。
Avatar
omochimetaru 18-Aug-17 03:55 AM
そう書かれてましたw
Avatar
koher 18-Aug-17 03:56 AM
なるほどw
Avatar
omochimetaru 18-Aug-17 03:56 AM
Make async default to throws
03:56
あ、これはおもしろいな
03:56
asyncならthrowsが暗黙で、 一方で、 async(nonthrowing) を導入する
Avatar
koher 18-Aug-17 03:56 AM
あー、それは考えなかったな。
03:56
確かにそれはあり得るな。
Avatar
omochimetaru 18-Aug-17 03:57 AM
but in the opinion of the proposal authors, this is probably the right set of tradeoffs.
03:57
ラトナ推し
Avatar
koher 18-Aug-17 03:57 AM
async(nonthrowing) より async nonthrows とかの方がいいな。 nonthrows は英語的におかしそうだけど。
Avatar
omochimetaru 18-Aug-17 03:58 AM
C++は nothorw があるよ
Avatar
koher 18-Aug-17 03:58 AM
throws がよくなかった気がするな。 Java のせいだけど。
03:58
throwing func とか async func とかの方が英語的によかったかも。 (edited)
03:58
nonthrowing func だったら nonmutating func とかとも整合するし。
Avatar
omochimetaru 18-Aug-17 04:00 AM
rethrows could be generalized to support potentially async operations
04:01
It would be possible to define a similar mechanism to allow abstraction over async operations as well.
04:01
reasyncかいてあった
Avatar
koher 18-Aug-17 04:01 AM
↓相当のものもほしいよね?
do { let a = await foo() let b = await bar(a) ... } wait
04:01
おお < reasync
Avatar
omochimetaru 18-Aug-17 04:02 AM
うーん・・・
Avatar
koher 18-Aug-17 04:02 AM
同期化のための簡単な手段は必要だと思う。
04:02
await! もいいけど、まとめてブロックも必要かと。
Avatar
omochimetaru 18-Aug-17 04:03 AM
それって、ランタイムの仕様規定なしで実現できないですよね?
04:03
Blocking calls Affordances could be added to better call blocking APIs from async functions and to hard wait for an async function to complete. There are significant tradeoffs and wide open design space to explore here, and none of it is necessary for the base proposal.
04:03
↑proposalとして触れてはいますね
Avatar
koher 18-Aug-17 04:03 AM
なるほど。
Avatar
omochimetaru 18-Aug-17 04:03 AM
この提案自体は、並列実行メカニズム自体からは分離して
04:04
coroutineだけで議論できる範囲にとどめていて
04:04
Potential Future Directions
の章でblockingについて書いてあった。
Avatar
koher 18-Aug-17 04:04 AM
let a = await foo() let b = await bar()
のときに foobar を並列に走らせるのか直列に走らせるのかはどうだろう?
Avatar
omochimetaru 18-Aug-17 04:05 AM
あ、それ自体は Futureとして出てきますよ
04:05
func processImageData1a() async -> Image { let dataResource = Future { await loadWebResource("dataprofile.txt") } let imageResource = Future { await loadWebResource("imagedata.dat") } // ... other stuff can go here to cover load latency... let imageTmp = await decodeImage(dataResource.get(), imageResource.get()) let imageResult = await dewarpAndCleanupImage(imageTmp) return imageResult }
04:05
Futureのコンストラクタで beginAsync していて
04:06
get() async throws -> T なので
04:06
dataResourceとimageResourceの取得は並列に起動して
Avatar
koher 18-Aug-17 04:06 AM
じゃあトピックは網羅されてそうだ。
Avatar
omochimetaru 18-Aug-17 04:06 AM
decodeImageの呼び出しのところで両方を待つ。
04:07
Futureはproposalの中のただの話題なのか、std導入の話なのかは読み飛ばした
Avatar
koher 18-Aug-17 04:08 AM
ほぼ思い描いていた通りのもので満足だ。
Avatar
omochimetaru 18-Aug-17 04:08 AM
同じく
04:09
もともとの非同期manifesto側では、actorモデル導入の段階でランタイムの話が出てきて、既存のGCDにうまく乗っかれると思う、みたいなことが書いてあった。
Avatar
koher 18-Aug-17 06:49 AM
async/awai に続いて Typed throws も。
Typed throws is something we need to settle one way or the other, and I agree it would be nice to do that in the Swift 5 cycle.
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170814/038928.html
Avatar
omochimetaru 18-Aug-17 06:50 AM
マジか
Avatar
koher 18-Aug-17 06:50 AM
ただ、こっちはどういう方向になるか未知数。
06:50
↑に、 Error が existential だからパフォーマンスが、ってことが書かれていて興味深い。
Avatar
omochimetaru 18-Aug-17 06:51 AM
パフォーマンスが、なんですか?
Avatar
koher 18-Aug-17 06:51 AM
One thing that I’m personally very concerned about is in the systems programming domain. Systems code is sort of the classic example of code that is low-level enough and finely specified enough that there are lots of knowable things, including the failure modes. Beyond expressivity though, our current model involves boxing thrown values into an Error existential, something that forces an implicit memory allocation when the value is large. Unless this is fixed, I’m very concerned that we’ll end up with a situation where certain kinds of systems code (i.e., that which cares about real time guarantees) will not be able to use error handling at all.
Avatar
omochimetaru 18-Aug-17 06:53 AM
existentialにラップするためのヒープ確保がある限り、時間保証したいような場面で今のままじゃ全く使えん?
06:53
JohnMC has some ideas on how to change code generation for ‘throws’ to avoid this problem, but I don’t understand his ideas enough to know if they are practical and likely to happen or not.
06:54
それを解決するアイデアってなんだ・・・?TypedThrowsになれば型のサイズが固定されるから解決するという話とは別で、Errorに対してやりようがあるってことかな
Avatar
koher 18-Aug-17 06:55 AM
JohnMC has some ideas on how to change code generation for ‘throws’ to avoid this problem, but I don’t understand his ideas enough to know if they are practical and likely to happen or not.
で、 Chris Lattner のこのメールに John McCall が返信してるから、それ見たらわかるかも。
Avatar
omochimetaru 18-Aug-17 06:55 AM
なるほど
Avatar
koher 18-Aug-17 07:28 AM
@omochimetaru と Error Handling Rational and Proposal の英語は難しかった話をしたけど、今見てもやっぱり難しい。↓ Universal error についての一節。
This combination of requirements means that all operations must be implicitly "unwindable" starting from almost any call site it makes. For the stability of the system, this unwinding process must restore any invariants that might have been temporarily violated; but the compiler cannot assist the programmer in this. The programmer must consciously recognize that an error is possible while an invariant is broken, and they must do this proactively --- that, or track it down when they inevitably forget. This requires thinking quite rigorously about one's code, both to foresee all the error sites and to recognize that an important invariant is in flux. How much of a problem this poses depends quite a lot on the code being written. There are some styles of programming that make it pretty innocuous. For example, a highly functional program which conscientiously kept mutation and side-effects to its outermost loops would naturally have very few points where any invariants were in flux; propagating an error out of an arbitrary place within an operation would simply abandon all the work done up to that point. However, this happy state falls apart quite quickly the more that mutation and other side-effects come into play. Complex mutations cannot be trivially reversed. Packets cannot be unsent. And it would be quite amazing for us to assert that code shouldn't be written that way, understanding nothing else about it. As long as programmers do face these issues, the language has some responsibility to help them.
Avatar
koher 18-Aug-17 07:36 AM
↓モナド?
More generally, by modeling both `throws` and `async` as effects on function types, we can eventually provide common abstraction tools to abstract over both effects in protocols and generic code
https://gist.github.com/lattner/429b9070918248274f25b714dcfc7619#rethrows-could-be-generalized-to-support-potentially-async-operations
Concrete proposal for async semantics in Swift
Avatar
omochimetaru 18-Aug-17 07:37 AM
throws and async as effects on function types,
07:37
effects ってのが専門用語を匂わせてる気がする
07:38
eff言語では effect としてモナド変換を一級に扱える http://www.eff-lang.org
Avatar
koher 18-Aug-17 07:38 AM
うん、本質的には同じものだと思う。
Avatar
omochimetaru 18-Aug-17 07:38 AM
あとハスケルにもEffectsって言葉があって、同じような領域の概念っぽいけどよくしらない http://konn-san.com/prog/haskell/extensible-effects.html
👀 1
Avatar
ukitaka 18-Aug-17 07:41 AM
http://nineties.github.io/category-seminar/13.html#/55 この辺わかりやすいです。effect = 計算作用のことかと
Avatar
omochimetaru 18-Aug-17 07:41 AM
おお、ありがとうございます
07:42
2013年 圏論勉強会 資料
07:42
良さそう
Avatar
koher 18-Aug-17 07:44 AM
スライドがめくれない・・・
Avatar
t.ae 18-Aug-17 07:44 AM
カーソル左右
Avatar
koher 18-Aug-17 07:44 AM
おお、ずっとマウスで操作してた。ありがとう。
07:49
本当に圏論の話だった・・・ これは最初から丁寧に追わないとわからなさそうだ。
Avatar
omochimetaru 18-Aug-17 09:08 AM
エラーのアロケーション回避は、Tagged Pointerにしたらいいよってやつだった。
09:08
ポインタに直接整数いれたりするやつ。
Avatar
koher 19-Aug-17 12:27 AM
これまで await try と書いてたけど、プロポーザル通り try await じゃないといけない気がしてきた。
00:28
tryawaitflatMap と等価でモナドを剥がすわけだけど、 async throwsPromise が外側だからまず Promise を剥がさないといけず、その後 Result を剥がすと考えると try await じゃないとおかしい。
Avatar
koher 19-Aug-17 04:05 AM
beginAsyncrethrowsbodythrows ってやっぱダメじゃない?
04:06
I agree. I think `rethorws` for `beginAsync` is problematic. For example, what happens when the `foo` in the following code throws an `Error` asynchronously? func foo() async throws { ... } beginAsync(foo) `foo` is acceptable as `beginAsync`'s `body` by its type. However its error might be thrown asynchronously and it is impossible to rethrow it. So the error must be ignored or treated as an universal error by untyped propagation. It breaks type safety about error handling. So I think the signature of `beginAsync` should be the following one. func beginAsync(_ body: () async -> Void) -> Void
Avatar
omochimetaru 19-Aug-17 10:52 AM
bodyのsuspend後に発生するthrowについては、beginAsyncのrethrowsとは関係ないですね
10:52
/// If the async process completes by /// throwing an error before suspending itself, beginAsync rethrows the error.
10:53
beginAsyncのドキュメントには、suspend後の再開後についてのエラーがどうなるか書いてないですね
10:55
今の状態は、 suspend前のthrowをrethrowsして、suspend後については書いてない @koher の案は、 suspend後も前もthrow禁止にして、ユーザ側の昇格に任せる
Avatar
koher 19-Aug-17 11:10 AM
うん、それがまずい気がする。別に再開後のエラーで universal error 化したければ明示的に catch して fataError 呼べばいいだけだし、 await 前については beginAsync のクロージャの外に出せるはず。せっかく型安全な typed propagation を選択したのに、型チェックが働かなくなってる。
Avatar
omochimetaru 19-Aug-17 11:11 AM
await 前については beginAsync のクロージャの外に出せるはず。
あ~そっか、それはたしかに。
Avatar
koher 19-Aug-17 11:13 AM
だから beginAsync のbody に throws を許してうれしい理由がない気がする。
Avatar
koher 21-Aug-17 01:33 AM
await! についても違う方向で話されてたから blocking のことに言及してみた。 https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170814/039096.html
Avatar
tarunon 21-Aug-17 01:48 AM
throwsと対称性のある形になってくると嬉しいですね、do構文の取り回しとしても
🙂 1
Avatar
koher 22-Aug-17 07:17 AM
async(nonthrowing) おもしろいけど、それをやっちゃうと throws, async に続く第三のエフェクトを導入したときに整合性をとるのに困ると思う。
Avatar
omochimetaru 22-Aug-17 08:11 AM
たしかに。
Avatar
koher 23-Aug-17 01:24 AM
昔の SwiftJP Slack のログをサルベージしてみたんだけど、 2016-03-28 時点で今の Chris Lattner の async/await の Proposal と同じような内容が話されてる。 https://gist.github.com/koher/5cd16adac7a62b6d3eb0b910ccc13534
01:24
出て来るメンバーが今と変わってないw
Avatar
omochimetaru 23-Aug-17 01:28 AM
Swift3の間は細かい事しか変わってないから知見のレベルに変化が無い・・・
Avatar
t.ae 23-Aug-17 02:03 AM
import Accelerate extension Array where Element: Comparable { mutating func clip(low: Element, high: Element) { print("normal version") for i in 0..<self.count { self[i] = Swift.max(Swift.min(self[i], high), low) } } @_specialize(Float) func clipped(low: Element, high: Element) -> [Element] { var ret = self ret.clip(low: low, high: high) return ret } } extension Array where Element == Float { mutating func clip(low: Float, high: Float) { print("accelerate version") var low = low var high = high self.withUnsafeMutableBufferPointer { bp in let p = bp.baseAddress! vDSP_vclip(p, 1, &low, &high, p, 1, vDSP_Length(bp.count)) } } } var int = (0..<10).map { Int($0) } int.clipped(low: 3, high: 5) // normal version int.clip(low: 3, high: 5) // normal version var x = (0..<10).map { Float($0) } x.clipped(low: 3, high: 5) // normal version x.clip(low: 3, high: 5) // acceerate version
Float用のclippedを多重実装せずにaccelerate versionを呼べないかと思ってるんですが@_specializeでもだめっぽい……
(edited)
Avatar
koher 23-Aug-17 02:06 AM
@_specialize ってそのメソッドや関数の型パラメータに利くんじゃないっけ?
02:06
メソッドをジェネリックな private func 化して
02:06
それに @_specialize 付けるとか?
02:06
ダメか
Avatar
omochimetaru 23-Aug-17 02:06 AM
protocol ArrayClippable を用意して
Avatar
t.ae 23-Aug-17 02:06 AM
自分自身の型パラには効かないんでしたっけ?
02:06
ちょっと試してみます
Avatar
koher 23-Aug-17 02:06 AM
呼び出し元で existential になってる?
Avatar
omochimetaru 23-Aug-17 02:06 AM
Arrayのメソッドはそれを呼ぶだけにするとかでできないかな
02:08
あとで読もう・・・。
Avatar
omochimetaru 23-Aug-17 02:10 AM
protocol ArrayClippable { static func clipArray(_ array: inout Array<Self>, min: Self, max: Self) } extension ArrayClippable { static func clippedArray(_ array: Array<Self>, min: Self, max: Self) -> Array<Self> { var ret = array Self.clipArray(&ret, min: min, max: max) return ret } } extension Array where Element : ArrayClippable { mutating func clip(min: Element, max: Element) { Element.clipArray(&self, min: min, max: max) } func clipped(min: Element, max: Element) -> Array<Element> { return Element.clippedArray(self, min: min, max: max) } }
Avatar
t.ae 23-Aug-17 02:11 AM
conditional conformanceが必要な気がしますがどうですかね?
Avatar
omochimetaru 23-Aug-17 02:12 AM
extension Comparable : ArrayClippable { static func clipArray(_ array: inout Array<Self>, min: Self, max: Self) { // ... } }
Avatar
koher 23-Aug-17 02:12 AM
@t.ae どうやってスペシャライズされてないことを確認したの?
Avatar
omochimetaru 23-Aug-17 02:12 AM
@koher printでは?
Avatar
t.ae 23-Aug-17 02:12 AM
呼び出ししか見てないです
Avatar
omochimetaru 23-Aug-17 02:12 AM
print("accelerate version")
02:13
@t.ae ↑の Comaprable : ArrayClippable も置いとけばいけるきがするけど駄目かな
Avatar
t.ae 23-Aug-17 02:13 AM
のでspecializeされてないのか、specializeされてるけど言語機能的に呼び出しがやってほしいほうに向かないのかは不明です
Avatar
omochimetaru 23-Aug-17 02:13 AM
vDSP_vclipが呼ばれるときは printが走るからわかるんじゃ?
Avatar
t.ae 23-Aug-17 02:13 AM
あーArrayClippableってエレメントのほうにつけるやつなんですね
Avatar
omochimetaru 23-Aug-17 02:13 AM
そうそう。
Avatar
koher 23-Aug-17 02:13 AM
あー、そういうことか。色々勘違いしてた。
02:14
@_specialize で呼び分けるのは無理なんじゃないかな?
Avatar
t.ae 23-Aug-17 02:20 AM
Playground execution failed: error: MyPlayground.playground:10:1: error: extension of protocol 'Comparable' cannot have an inheritance clause extension Comparable: ArrayClippable { ^ ~~~~~~~~~~~~~~
つけられない?
Avatar
omochimetaru 23-Aug-17 02:21 AM
あ、ほんとだ
Avatar
t.ae 23-Aug-17 02:22 AM
これってなんの制限なんですっけ
Avatar
omochimetaru 23-Aug-17 02:22 AM
プロトコルにはプロトコルを後付できない?
Avatar
koher 23-Aug-17 02:22 AM
できないね。 < 後付 (edited)
Avatar
omochimetaru 23-Aug-17 02:22 AM
じゃあComparable向けに実装が必要になっちゃうなあ
Avatar
t.ae 23-Aug-17 02:23 AM
extensionで追加ができないだけなのか。
Avatar
t.ae 23-Aug-17 02:32 AM
ところでSwift4でspecializeの文法変わるんですね。 https://github.com/apple/swift/blob/master/docs/Generics.rst#specialization
swift - The Swift Programming Language
02:32
ドキュメント読んで書いて実行できなくて気づいたんですが
02:34
ん?exportedとかいうのが追加されててそれが関係ある気が
Avatar
omochimetaru 23-Aug-17 02:34 AM
If 'exported' is set, the corresponding specialization would have a public visibility and can be used by clients. If 'exported' is omitted, it's value is assumed to be 'false'.
02:34
外から呼べるみたいだね
Avatar
t.ae 23-Aug-17 02:35 AM
実質多重実装をしてくれることになるのかな?
Avatar
koher 23-Aug-17 02:35 AM
@t.ae
@_specialize について、 _ で始まるものは本当に使わないほうがいいです。意図的にやっているのかっていうくらい頻繁に仕様が変わります。
by @rintaro
Avatar
omochimetaru 23-Aug-17 02:36 AM
struct S<T> { var x: T @_specialize(where T == Int, U == Float) mutating func exchangeSecond<U>(_ u: U, _ t: T) -> (U, T) { x = t return (u, x) } }
02:36
多分外から見ると
Avatar
koher 23-Aug-17 02:36 AM
まあでも Swift では _ に限らず破壊的変更がどのみち入るから(😭 )ついでに直せばいいだけな気も。 (edited)
Avatar
t.ae 23-Aug-17 02:36 AM
不安定感を込めて_付きなんでしょうかね
02:37
@koher 機能自体が無くなるとかがなければそうですね (edited)
Avatar
omochimetaru 23-Aug-17 02:38 AM
struct S<T> { var x: T mutating func exchangeSecond<U>(_ u: U, _ t: T) -> (U, T) { x = t return (u, x) } } extension S where T == Float { mutating func exchangeSecond(_ u: Int, _ t: Float) -> (Int, Float){ x = t return (u, x) } }
02:38
こうみえるんじゃないかな
Avatar
t.ae 23-Aug-17 02:39 AM
betaでexported試してみたけど変わらず。。。
Avatar
omochimetaru 23-Aug-17 02:39 AM
今のケースはそもそも
02:39
特殊化の話とは関係ないと思うよ
Avatar
koher 23-Aug-17 02:39 AM
@t.ae 機能がなくなっても最悪 @_specialize をなくせば動きはするしね。
Avatar
omochimetaru 23-Aug-17 02:40 AM
このspecializeは
02:40
どのwhereが該当するか決まった上で
02:41
substituteされた実際のconcrete typeのバージョンがオーバーロードとして生成される話だから (edited)
02:41
where Element : Comparable のセクションをコンパイルしている時点では
02:41
Element == Float へのディスパッチは考慮されないと思う
02:42
specialize過程での改めてのwhere選択はされないんじゃないかなあ
Avatar
koher 23-Aug-17 02:42 AM
うん。なので当初の問題を解決するのは @_specialize では無理だと思う。
Avatar
omochimetaru 23-Aug-17 02:42 AM
specializeはあくまで最適化過程の話であって、
Avatar
t.ae 23-Aug-17 02:42 AM
そこのディスパッチを考慮してくれるんじゃないかなと思ってたんですよね。 specializeは単純にオーバーロードを自前実装するのと同じだという認識でした。
Avatar
omochimetaru 23-Aug-17 02:43 AM
それが無かった場合と同じ結果にならないといけない
02:43
と考えると
02:43
where Element : Comparable の時点で、本当はFloatであるっていう意味情報は
02:43
Swiftレベルでは失われるから。
02:44
最適化してはじめてわかる「今はFloat」ってことに基づいて動作が変わっちゃうと
Avatar
t.ae 23-Aug-17 02:44 AM
それが無かった場合と同じ結果にならないといけない
これは納得。
Avatar
omochimetaru 23-Aug-17 02:44 AM
最適化によって結果が変わる(今回ならprint副作用が生じる)
02:44
ことになるからそれはやらなそう。
Avatar
t.ae 23-Aug-17 02:44 AM
なるほど。ありがとうございます。
Avatar
t.ae 25-Aug-17 08:27 AM
https://github.com/t-ae/SeveralPerformanceChecks/blob/master/Tests/SeveralPerformanceChecksTests/ManagedBufferArrayTests.swift#L18-L38 同一の実装のMyArrayMyArray2なんですが、同じテストコードでモジュール外にあるMyArrayの方が数百倍遅くて原因が分かりません。 モジュールまたぐ時ってwhole module optimization以外何かありましたっけ?
Contribute to SeveralPerformanceChecks development by creating an account on GitHub.
Avatar
rintaro 25-Aug-17 08:28 AM
specialization が効かないです。
Avatar
t.ae 25-Aug-17 08:28 AM
ジェネリクスのですよね? それだけでここまで変わるかなあと思うんですが
08:29
非ジェネリックなのを書いてみればいいか。
Avatar
omochimetaru 25-Aug-17 08:29 AM
ジェネリックなコードは遅いゾイ
08:29
time profiling してみたら?
08:29
xcodeのやつ
Avatar
t.ae 25-Aug-17 08:30 AM
spmでつくってるとそれを実行するまでが面倒くさいんですよねぇ
Avatar
omochimetaru 25-Aug-17 08:31 AM
generate-xcodeprojでmac向けならうまくいかん?
Avatar
t.ae 25-Aug-17 08:31 AM
command line toolのスキーム追加するのが一番簡単そうですかね
Avatar
omochimetaru 25-Aug-17 08:32 AM
勝手にできないのか・・・
Avatar
t.ae 25-Aug-17 08:38 AM
確かに非ジェネリックと比べると300倍以上遅いっぽい……
08:38
MyArrayみたいなのは作らないのが良いのかなぁ
Avatar
omochimetaru 25-Aug-17 08:38 AM
MyArray何?
Avatar
t.ae 25-Aug-17 08:39 AM
ManagedBufferを使って作った初期化しないイニシャライザ持ちのstructです
Avatar
omochimetaru 25-Aug-17 08:40 AM
遅かったのは度のテスト?
08:40
あー
08:40
MyArray2はテストコードに書いてあるのか。
Avatar
t.ae 25-Aug-17 08:40 AM
はい。
Avatar
omochimetaru 25-Aug-17 08:41 AM
これって
08:41
filterは
08:42
extension Collectionから来てる?
Avatar
t.ae 25-Aug-17 08:42 AM
はい。
08:42
というかmakeIteratorからですね
Avatar
omochimetaru 25-Aug-17 08:42 AM
えーっと、自作したのは
08:43
startIndex, indexofafter, subscriptだよね
Avatar
t.ae 25-Aug-17 08:43 AM
です。それだけあればmakeIteratorCollectionに生えているのが使えるので
Avatar
omochimetaru 25-Aug-17 08:44 AM
非ジェネリックと比べると
これは
08:44
テストとは別のモジュールでも
08:44
型パラ取らないやつにしたら早かったってこと?
Avatar
t.ae 25-Aug-17 08:44 AM
そうです。
08:44
MyArrayとおなじところにMyFloatArrayを作ってためしました
Avatar
omochimetaru 25-Aug-17 08:45 AM
あーなるほど・・・・
08:45
subscript使って要素を読み書きするところで
08:45
毎回boxingされてそうだね
Avatar
t.ae 25-Aug-17 08:45 AM
ですねぇ
Avatar
omochimetaru 25-Aug-17 08:46 AM
たぶんsilみると
08:46
alloc_box とか
08:46
めっちゃ出てくるんじゃないかな
08:47
せっかくManagerBufferでストレージは生のレイアウトなのに
08:47
subscript が getter / setter だから
08:47
遅くなっちゃうってのもありそうだな
Avatar
t.ae 25-Aug-17 08:48 AM
自前Iterator用意したら少しは早くなるかな
Avatar
omochimetaru 25-Aug-17 08:48 AM
いや、変わらんと思う
Avatar
t.ae 25-Aug-17 08:49 AM
あ、subscriptじゃなくて直接メモリ見に行くIteratorですよ
Avatar
omochimetaru 25-Aug-17 08:49 AM
SwiftのIteratorじゃなくてってこと?
Avatar
t.ae 25-Aug-17 08:49 AM
IteratorProtocolに従う別のIterator
Avatar
omochimetaru 25-Aug-17 08:50 AM
いまいちわからんけど UnsafeMutablePointer<T>.pointee を介した読み書きなら早いと思う
08:51
IteartorProtocolに従う限り
08:51
Collectionのfilterが
08:51
結果をコンストラクトして
08:51
つめるところで
08:51
subscriptへのgetter/setterが走りまくって
08:51
そこのboxingで重くなると思う。
Avatar
t.ae 25-Aug-17 08:55 AM
やってみましたけど遅いままですねぇ
08:56
素直にArrayに詰めたいけれど型が不定だと初期値をどうするのやら
Avatar
omochimetaru 25-Aug-17 08:56 AM
あれ?っていうか
08:56
現状のコードはあってるの?
08:56
uninitializedなメモリに対して
08:57
assignされちゃうのでは
Avatar
t.ae 25-Aug-17 08:58 AM
https://gist.github.com/airspeedswift/1fb7d6e3e73e53ce64f6 このへんを参考にしました
Array using ManagedBuffer
08:58
a-
08:59
countで確保するとこに問題あるのか。
Avatar
omochimetaru 25-Aug-17 09:00 AM
あーこうなってんのか
09:00
init(count: Int) でコンストラクトしたとき
09:00
メモリがuninitializedになっていて
09:00
その状態でsubscript setとかすると
09:00
バグだね
09:00
未定義動作しうる。
Avatar
koher 25-Aug-17 09:02 AM
@t.ae ちなみにこの airspeedswift さんは今 Apple の Swift Core Team になったよ。
Avatar
t.ae 25-Aug-17 09:04 AM
何かのPRで見ましたね。
Avatar
omochimetaru 25-Aug-17 09:06 AM
ジェネリックなArrayが高速に実現できないの微妙だなあ
09:06
それこそ、魔法の specialize 指定したら
09:06
どうなん
Avatar
t.ae 25-Aug-17 09:07 AM
specializeをどこにつければいいのやら
Avatar
koher 25-Aug-17 09:08 AM
全メソッドに Float に対して付けるんじゃないの?
Avatar
t.ae 25-Aug-17 09:08 AM
getの前につければいいのか
Avatar
koher 25-Aug-17 09:08 AM
SwiftPM だったらソースあるんだからスペシャライズしてくれたらいいのに・・・
Avatar
t.ae 25-Aug-17 09:09 AM
spm外から使う時のことを考えると早期に遅い部分が見つかるとも言える
Avatar
omochimetaru 25-Aug-17 09:10 AM
ArrayとArrayBufferみたけどよくわからんな
09:10
@_semantics("array.init")
Avatar
t.ae 25-Aug-17 09:10 AM
そのへん入り組んでて何がどうなってんのかわからないんですよね
Avatar
omochimetaru 25-Aug-17 09:10 AM
めっちゃ専用の最適化マークみたいなのついとるし。
09:11
これってfilterの結果を構築する部分はどれを使ってるんだろう
Avatar
t.ae 25-Aug-17 09:11 AM
とりあえずspecialize付けるくらいだと早くならなそうでした
Avatar
omochimetaru 25-Aug-17 09:11 AM
init(repeatedValue) で初期化した後に、subscriptで0から埋めてるのかな
Avatar
t.ae 25-Aug-17 09:11 AM
arrayでreserveCapacityかと
Avatar
omochimetaru 25-Aug-17 09:11 AM
reserveCapacity実装してある?
Avatar
t.ae 25-Aug-17 09:12 AM
中身見てないです
Avatar
omochimetaru 25-Aug-17 09:12 AM
あ、filterは
09:12
これArrayが返るのか
09:12
MyArrayが返ると思ってた
09:12
じゃあgetしてるだけか
Avatar
t.ae 25-Aug-17 09:12 AM
そうですね
09:12
filterというかイテレートの速度を見たかったので
Avatar
omochimetaru 25-Aug-17 09:13 AM
なるほど
Avatar
t.ae 25-Aug-17 09:13 AM
(for だと基準になるやつが速すぎて最適化で消えてる疑惑があったので)
Avatar
norio_nomura 01-Sep-17 02:00 AM
import Foundation var data = Data(bytes: [0x50, 0x4B, 0x01, 0x02, 0x41, 0x61]) data.removeFirst() print(data.startIndex) // swift-3.1: "0\n", swift-4.0: "1\n" data.customMirror // crash on swift-4.0 https://bugs.swift.org/browse/SR-5811
(edited)
Avatar
omochimetaru 01-Sep-17 02:01 AM
Swift3.1だと詰めなおしてたけどSwift4はstartIndexをずらすだけの効率的な実装になった?
Avatar
norio_nomura 01-Sep-17 02:02 AM
そう。
Avatar
omochimetaru 01-Sep-17 02:02 AM
お〜 いいね おしゃれ
02:02
customMirrorがクラッシュするのは何w
Avatar
norio_nomura 01-Sep-17 02:03 AM
swift - The Swift Programming Language
Avatar
omochimetaru 01-Sep-17 02:03 AM
0が範囲チェックされて死ぬのかw
Avatar
norio_nomura 01-Sep-17 02:05 AM
😁 1
Avatar
koher 01-Sep-17 07:20 AM
↑の Data の件、 Array と挙動が違って混乱を招くかも?
Welcome to Apple Swift version 4.0 (swiftlang-900.0.59 clang-900.0.34.2). Type :help for assistance. 1> var array = [2, 3, 5] array: [Int] = 3 values { [0] = 2 [1] = 3 [2] = 5 } 2> print(array.startIndex) 0 3> array.removeFirst() $R0: Int = 2 4> print(array.startIndex) 0
Avatar
omochimetaru 01-Sep-17 07:20 AM
startIndexが0であるかどうかとかは前提にしないべきなのでは?
07:21
Arrayにおいては前提なのかな?
Avatar
koher 01-Sep-17 07:21 AM
でも subscriptindexstartIndex が最初の要素を指すよ。
Avatar
omochimetaru 01-Sep-17 07:22 AM
DataのIndexがInt互換なのがまずい気がしてきた
07:23
UTF8Viewとか使うときは、IndexがIntとは違う専用の抽象的な型になってるから
Avatar
koher 01-Sep-17 07:23 AM
1> import Foundation 2> var data = Data(bytes: [2, 3, 5]) 3> print(data.startIndex) 0 4> data.removeFirst() $R0: UInt8 = 2 5> print(data.startIndex) 1 6> print(data[1]) 3
(edited)
Avatar
omochimetaru 01-Sep-17 07:23 AM
雑に 0 とかそもそもかけなくて
07:23
startIndex と advance で書いていくことになって安全
Avatar
koher 01-Sep-17 07:23 AM
えー
07:23
String と違って普通にランダムアクセスしたいでしょ?
07:24
i バイト目なんだから Int で適切だと思うけど。
Avatar
omochimetaru 01-Sep-17 07:25 AM
いまはadvanceじゃないんだった
07:25
index(_:offsetBy:)
07:25
ランダムアクセス自体はCollection protocolならできるから
Avatar
koher 01-Sep-17 07:25 AM
Array は必ず startIndex0endIndexcount - 1 として、わざわざ ArraySlice という型を設けて分離しているのに対して Data は一つの型でやってしまっていることと
Avatar
omochimetaru 01-Sep-17 07:26 AM
collection.index(collection.startIndex, offsetBy: 6) -> 6番目の要素のIndexが返る
07:26
collection [ collection.index(collection.startIndex, offsetBy: 6) ] -> 6番目の要素を取得
Avatar
koher 01-Sep-17 07:26 AM
removeFirststartIndex に影響を及ぼすのか及ぼさないのかという仕様の違いをどっちも混ぜてしまったのが問題では。
07:27
1> var ns: ArraySlice<Int> = [2, 3, 5] ns: ArraySlice<Int> = 3 values { [0] = 2 [1] = 3 [2] = 5 } 2> print(ns.startIndex) 0 3> ns.removeFirst() $R0: Int = 2 4> print(ns.startIndex) 1
07:27
ArraySlice とは一貫してるのか
07:27
じゃあ Data は最初からスライスだと考えれば良いのか。
07:28
String.UTF8Viewはデータ構造上O(1)ランダムアクセスができないからCollectionにはなってなくて
07:28
index(_: offsetBy) はつかえないから、 index(after: ) で、+1ずつすすめていかないといけないことが
07:28
型で表現されてる
Avatar
koher 01-Sep-17 07:29 AM
うん、 Data はそういうのとは違うから
07:29
Int で適切だと思う。
07:29
ちなみに EasyText なら O(1) ランダムアクセスできるよ。
Avatar
omochimetaru 01-Sep-17 07:30 AM
それは一回全部書記素クラスタの配列にしてるからですよね (edited)
Avatar
koher 01-Sep-17 07:30 AM
うん、なので初期化は普通の String より遅いけど、計算量のオーダーは同じ。
07:31
UTF-8 バイト列から String インスタンスを作るのと大して変わらない。
Avatar
omochimetaru 01-Sep-17 07:32 AM
書記素クラスタ一つ一つは可変長データ構造だから
Avatar
koher 01-Sep-17 07:32 AM
うん
07:32
ヒープにいっぱい
Avatar
omochimetaru 01-Sep-17 07:32 AM
ヒープ上の構造としては2次元になっちゃうんじゃないですか
Avatar
koher 01-Sep-17 07:32 AM
領域を確保しなきゃいけないというのはある。
Avatar
omochimetaru 01-Sep-17 07:32 AM
データ構造としては絶対そっちのほうが取り扱いやすいけど
Avatar
koher 01-Sep-17 07:32 AM
いや、でも
07:32
String から構築してるから
07:33
String がヒープに確保してるでっかい領域を
07:33
Character が参照してるだけになるのでは?
Avatar
omochimetaru 01-Sep-17 07:33 AM
あー SubStringのチャンク共有でうまくいくのかな
Avatar
koher 01-Sep-17 07:34 AM
String から characters を取り出したときに内部的にどうなってるか詳しいことはしらない。
07:35
ランダムアクセスが多発する処理をするなら String より EasyText の Text の方が速そう。
Avatar
omochimetaru 01-Sep-17 07:35 AM
ランダムアクセスのやり方にもいろいろあって
07:36
先読みパーサーみたいなものを実装する場合は
07:36
すでに訪問したIndexに戻る場合に限っては
07:36
O(1)で飛べるんですよね
Avatar
koher 01-Sep-17 07:36 AM
そうだね。
07:37
まあ、主な用途はパフォーマンスそんなに気にせずに簡単な API で雑に文字列を扱いたいときだね。
Avatar
omochimetaru 01-Sep-17 07:38 AM
(C++とかで)パーサー書こうとして、マルチバイト文字めんどくさいのでuint32_tの配列とかにしようとおもいつつ
07:39
utf8一個ずつ読んで、戻るときはindexに戻るだけで済ませられることがまれによくある
Avatar
koher 01-Sep-17 07:39 AM
それは書記素クラスタではなくコードポイントになってるのでは?
Avatar
omochimetaru 01-Sep-17 07:40 AM
はい
Avatar
koher 01-Sep-17 07:40 AM
マルチバイト文字めんどくさいのでuint32_tの配列
07:41
Swift の String がややこしいこと考えずに書記素クラスタで扱えるのはとても良いと思う。
Avatar
tarunon 06-Sep-17 08:49 AM
async/actorの議論でReactiveStreamなるスレッドが立ち上がってるけどあんまり追えてない
Avatar
koher 07-Sep-17 06:52 AM
!!
$ swift Welcome to Apple Swift version 4.0 (swiftlang-900.0.63.10 clang-900.0.36). Type :help for assistance. 1> : (lldb) script Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D. >>> [x * x for x in range(10)] [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] >>>
Avatar
omochimetaru 07-Sep-17 06:53 AM
え・・・
06:53
内包表記・・・
Avatar
tarunon 07-Sep-17 06:53 AM
pythonw
Avatar
omochimetaru 07-Sep-17 06:53 AM
夢では
Avatar
koher 07-Sep-17 06:53 AM
Swift の REPL 上で Python の REPL を立ち上げられる?
Avatar
omochimetaru 07-Sep-17 06:53 AM
ん???
Avatar
koher 07-Sep-17 06:53 AM
: が何かわかってない。
Avatar
omochimetaru 07-Sep-17 06:53 AM
pythonに切り変わってるのかwww (edited)
Avatar
koher 07-Sep-17 06:54 AM
なんか Swift の ML に↑みたいなのが流れてたのを見かけて真似したらできた。
Avatar
tarunon 07-Sep-17 06:54 AM
:でlldbにスイッチして
06:54
lldbはpythonだから〜ってことかしら
Avatar
omochimetaru 07-Sep-17 06:54 AM
さらに script ってこまんどで
06:54
lldb shellのなかでpython環境に入る気がする
06:55
[omochi@omochi-iMac SwiftSyntax (master *=)]$ swift Welcome to Apple Swift version 4.0 (swiftlang-900.0.63.10 clang-900.0.36). Type :help for assistance. 1> : (lldb) script Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D. >>> 3 + 3 6 >>> exit (lldb) ^D 1> ^D
06:55
3層 in / in / in / out /out /out
Avatar
koher 07-Sep-17 06:55 AM
なるほど
Avatar
tarunon 07-Sep-17 06:56 AM
>>> ^D (lldb) ^D 1> ^D $
06:56
ワロタ
Avatar
omochimetaru 07-Sep-17 06:56 AM
pythonもC-Dで抜けられるのねw
Avatar
tarunon 07-Sep-17 06:56 AM
せやで
Avatar
koher 07-Sep-17 06:57 AM
抜けられない REPL って何かあるっけ?
Avatar
omochimetaru 07-Sep-17 06:57 AM
swift
06:57
あ、逆か
Avatar
tarunon 07-Sep-17 06:57 AM
抜けれるでは
Avatar
omochimetaru 07-Sep-17 06:57 AM
exitで抜けられない
06:57
exit派だった
Avatar
koher 07-Sep-17 06:58 AM
node も抜けられた
Avatar
rintaro 07-Sep-17 06:58 AM
なら :exit
Avatar
omochimetaru 07-Sep-17 06:58 AM
oh
Avatar
koher 07-Sep-17 06:58 AM
irb も OK
Avatar
tarunon 07-Sep-17 06:58 AM
var exit: Never みたいなの生やせばexitで抜けれるようになるかしら
Avatar
omochimetaru 07-Sep-17 06:58 AM
なるほど C-D 派のほうが暮らしやすいのか
Avatar
koher 07-Sep-17 06:58 AM
ghci (Haskell) も OK
06:59
kotlinc もいけた。大体いけそう。
Avatar
rintaro 07-Sep-17 07:00 AM
$ swift Welcome to Apple Swift version 4.0 (swiftlang-900.0.63.10 clang-900.0.36). Type :help for assistance. 1> import Darwin 2> exit(0) REPL requires a running target process. error: REPL process is no longer alive, exiting REPL
なら抜けられる。
(edited)
Avatar
rintaro 07-Sep-17 08:12 AM
struct Hoge { var foo: Int = 0 var bar: Int = 0 } var hoge: Hoge = Hoge() { didSet { print("didSet") } }
みたいな、監視されている struct 値を更新するときに
hoge.foo = 12 hoge.bar = 13
(edited)
08:13
とかすると、二回didSetされちゃうのを避けるために、
08:13
_ = { $0.foo = 12 $0.bar = 13 }(&hoge)
っていう方法よりシンプルでわかりやすいのってありますか?
08:17
(hoge.foo, hoge.bar) = (12, 13)
これもだめ 😢
Avatar
t.ae 07-Sep-17 08:18 AM
hoge.mutateメソッドを生やしたら少し分かりやすいかも?
08:18
protocol Mutable { } extension Mutable { mutating func mutate(_ f: (inout Self)->Void) { f(&self) } } struct Hoge: Mutable { var foo: Int = 0 var bar: Int = 0 }
(edited)
Avatar
rintaro 07-Sep-17 08:20 AM
hoge.mutate { $0.foo = 12 $0.bar = 13 }
いいかも、使わせていただきまっす!
Avatar
t.ae 07-Sep-17 08:21 AM
Mutableプロトコルは名前が不自然なのでそこだけ変えて下さいw
Avatar
rintaro 07-Sep-17 08:31 AM
実際には RxSwift.Variable に使いたかっただけなのでこんな感じにしました。
extension RxSwift.Variable { func mutateValue(fn: (inout Element) -> Void) { fn(&value) } }
Avatar
tarunon 07-Sep-17 08:32 AM
あーーー
08:32
ある
08:32
わかる
08:32
RxSwift.Variable
08:32
setとgetそれぞれ単体ではlockされてるけど、通しでlockはできない問題がアッて
08:33
variable.value.foo = xxx
をマルチスレッドでやらかすと死ねる
Avatar
t.ae 07-Sep-17 08:33 AM
didSetの場合もですけど冪等に作っておいて多重実行は気にしないのが良いんですかね……
Avatar
tarunon 07-Sep-17 08:34 AM
Variable使わないほうがいいねっていう雰囲気はある
08:34
mutateでgetからsetまで通しでLockかければ死ぬ問題は回避できるので
08:34
extension RxSwift.Variable { func mutateValue(fn: (inout Element) -> Void) { _lock.lock() fn(&value) _lock.unlock() } }
できるかな?こんな感じが良さそう。
Avatar
rintaro 07-Sep-17 08:35 AM
なるほどー
Avatar
tarunon 07-Sep-17 08:38 AM
Variable周り、初期値なしのVariableも欲しいよねとか色々欲求はあって
08:38
前提案してみたんですがVariable自体をmain repoから切り出したいみたいで
08:38
それ完了してからって感じでしたね
08:39
mutateValueも絶対あったほうがいいけど、早く切り出されないかな。
Avatar
takasek 07-Sep-17 09:02 AM
Short description of the issue: I'd like to be able to share a Variable object, without allowing access to the setter of value. Expected outcome: Basically, it could be another type (e.g. ReadOnlyV...
Avatar
t.ae 21-Sep-17 10:27 AM
BinaryInteger導入で[T1: BinaryFloatingPoint][T2: BinaryInteger]に変換するメソッドが書けるようになって喜んでたら [T1: BinaryInteger][T2: BinaryFloatingPoint]に変換するほうができなかった
Avatar
t.ae 21-Sep-17 02:32 PM
SignedIntegerUnsignedIntegerに分けてそれぞれInt64, UInt64を経由して変換するというろくでもない方法に落ち着いてしまった
Avatar
koher 22-Sep-17 03:32 AM
今、↓を受け取ってこれをコンパイル時に検出できないのはおかしいんじゃないかと思ったけど、 Conditional Conformance がないからまだできない?
fatal error: Array<Foo> does not conform to Encodable because Pedestrian does not conform to Encodable.:
(edited)
Avatar
tarunon 22-Sep-17 03:33 AM
できないですね
Avatar
koher 22-Sep-17 03:33 AM
Conditional Conformance 待ち遠しいですねぇ。
03:33
Countable...Range を一掃できるのもうれしい。
Avatar
koher 22-Sep-17 03:48 AM
Argo ( Runes, Curry )を取り除いて Codable に置き換えた!
Avatar
omochimetaru 22-Sep-17 03:48 AM
CodableってJSONのどこがわるかったかってわかるんですっけ
03:49
あ、まあArgoならどうせわからないから関係ないか
Avatar
koher 22-Sep-17 03:51 AM
@omochimetaru Codable のエラーメッセージがどうなってるかは知らないけど、原理的にはパスをたどれそうな気がする。エラーが throw されてきたら素通しにせず、一度 catch してからエラーメッセージにパスを追記して throw しなおせばいいんじゃない?そうなってなかったら swift リポジトリへの PR チャンスかも?
Avatar
omochimetaru 22-Sep-17 03:52 AM
潜りながら追記していくんじゃなくて
03:52
例外の浮上に合わせて後ろから書いていくのか
03:53
あ〜全然思いつかなかったけどそれでもできるな
Avatar
norio_nomura 22-Sep-17 03:53 AM
Encoder, Decoderのエラーに含まれるパスは「とりあえずあるレベル」だと記憶。 (edited)
Avatar
omochimetaru 22-Sep-17 03:54 AM
そのほうがパスの取り回しが異常系だけになるしパフォーマンス的にも賢いな
Avatar
koher 22-Sep-17 03:54 AM
swift リポジトリじゃなくて foundation か。
03:56
いや、違うのか? Decoder につけなきゃいけないのか。
03:56
JSON に限った話じゃないか。
Avatar
tarunon 23-Sep-17 03:42 PM
Swiftのmain repositoryだと、String.CharacterViewってDeprecatedなんすね、無限に警告が出てくるw
Avatar
koher 26-Sep-17 12:38 AM
なんか前も話したかもだけど、 =>inout 版がほしい気がしてきた。
00:39
func =><T>(lhs: T, rhs: (inout T) throws -> ()) rethrows -> T { var value = lhs try rhs(&value) return value }
(edited)
00:39
みたいな感じ。
00:41
でも、↓とオーバーロードしたら嫌な感じで衝突しそう。
func =><T, U>(lhs: T, rhs: (T) throws -> U) rethrows -> U { return try rhs(lhs) }
Avatar
Biacco42 26-Sep-17 12:42 AM
そこはシグネチャ変えたほうが良さそうですね
Avatar
koher 26-Sep-17 12:53 AM
演算子でないと中置にできないから、新しい演算子導入するのは辛い・・・。
Avatar
Biacco42 26-Sep-17 12:54 AM
’==>’ はもう使っちゃったんでしたっけ?
Avatar
koher 26-Sep-17 12:54 AM
使ってないけどそういう問題じゃなくて、わけのわからない演算子を二つも導入するのは耐えられないなぁと。
Avatar
Biacco42 26-Sep-17 12:55 AM
まぁ、それはそうですね…
Avatar
koher 26-Sep-17 12:59 AM
さっき投稿した https://qiita.com/koher/items/344657d7a9ce85322c09 の中で書いた、
var teamToCount: [String: Int] = [:] for user in users { let team = user.team if let count = teamToCount[team] { teamToCount[team] = count + 1 } else { teamToCount[team] = 1 } }
を、もし inout 版の => があれば reduce(into:_:) を使わなくても
let teamToCount: [String: Int] = [:] => { teamToCount in for user in users { teamToCount[user.team, default: 0] += 1 } }
って書けそうだなぁと。
先日 Swift 4 がリリースされました。みんな注目しているのは Codable など劇的にコーディングが楽になる新機能だと思いますが、ちょっとした便利な小技もあります。 そんな、 Swift 4 の小技の魅力の一面を 3 行...
Avatar
Biacco42 26-Sep-17 01:12 AM
subscript にデフォルトなんてのが増えていたんですか
Avatar
koher 26-Sep-17 01:13 AM
めちゃくちゃ便利
01:14
↓なんかうまくいかない。何かミスってる??
infix operator => : SwifletPrecedence precedencegroup SwifletPrecedence { higherThan: AssignmentPrecedence associativity: left } func =><T>(lhs: T, rhs: (inout T) throws -> ()) rethrows -> T { var value = lhs try rhs(&value) return value } print([Int]() => { (a: [Int]) -> () in a.append(42) })
$ swift inout-let.swift inout-let.swift:14:40: error: value of type 'Any' has no member 'append' print([Int]() => { (a: [Int]) -> () in a.append(42) }) ^ ~~~~~~ inout-let.swift:14:40: note: cast 'Any' to 'AnyObject' or use 'as!' to force downcast to a more specific type to access members print([Int]() => { (a: [Int]) -> () in a.append(42) }) ^ ( as AnyObject)
(edited)
Avatar
rintaro 26-Sep-17 01:24 AM
{ (a: inout [Int]) -> () in a.append(42) } クロージャパラメータに inout が必要
01:25
推測させちゃったほうが楽ですね。
Avatar
tarunon 26-Sep-17 01:25 AM
ここもコミットチャンスだな
Avatar
koher 26-Sep-17 01:26 AM
なるほど、そこも inout がいるんですね・・・。考えてみれば当たり前だ。
01:27
推論はうまくいかなかったんですよねぇ・・・。
01:27
infix operator => : SwifletPrecedence precedencegroup SwifletPrecedence { higherThan: AssignmentPrecedence associativity: left } func =><T>(lhs: T, rhs: (inout T) throws -> ()) rethrows -> T { var value = lhs try rhs(&value) return value } print([Int]() => { (a: inout [Int]) -> () in a.append(42) }) print([Int]() => { a in a.append(42) }) print([Int]() => { $0.append(42) })
$ swift inout-let.swift inout-let.swift:15:25: error: value of type 'Any' has no member 'append' print([Int]() => { a in a.append(42) }) ^ ~~~~~~ inout-let.swift:15:25: note: cast 'Any' to 'AnyObject' or use 'as!' to force downcast to a more specific type to access members print([Int]() => { a in a.append(42) }) ^ ( as AnyObject) inout-let.swift:16:20: error: value of type 'Any' has no member 'append' print([Int]() => { $0.append(42) }) ^~ ~~~~~~ inout-let.swift:16:20: note: cast 'Any' to 'AnyObject' or use 'as!' to force downcast to a more specific type to access members print([Int]() => { $0.append(42) }) ^ ( as AnyObject)
Avatar
もあい 26-Sep-17 01:28 AM
Swift 4.1だと推論うまくいきますね
Avatar
koher 26-Sep-17 01:28 AM
Swift 4.1👀
01:28
こちらの環境はですね。
$ swift --version Apple Swift version 4.0 (swiftlang-900.0.63.10 clang-900.0.36) Target: x86_64-apple-macosx10.9
Avatar
rintaro 26-Sep-17 01:29 AM
3.2 でいけるからデグレってる。
01:29
あ、3.1
Avatar
koher 26-Sep-17 01:29 AM
reduce(into:_:) だとうまく推論できたのも謎。
01:29
↓これは動くんですよねぇ。
// 型の準備 struct User { var team: String } // 値の準備 let users = [ User(team: "A"), User(team: "B"), User(team: "B"), User(team: "A"), User(team: "C"), User(team: "A"), User(team: "C"), User(team: "B"), User(team: "D"), User(team: "A"), ] // 集計 let teamToCount: [String: Int] = users.reduce(into: [:]) { teamToCount, user in teamToCount[user.team, default: 0] += 1 } // 出力 for (team, count) in (teamToCount.sorted { $0.key < $1.key }) { print("\(team): \(count)") }
01:30
クロージャ式のteamToCountinout なんですが、問題なく通ります。
Avatar
rintaro 26-Sep-17 01:33 AM
あ、やっぱりXcode9/Swift3.2 でいけますね。 4.0 だけの問題か。<推論
Avatar
koher 26-Sep-17 01:34 AM
4.1 でも推論できるってことは、既知の問題で対処済みってことなんですかね。
01:34
発現条件が謎だ・・・
01:35
reduce(into:_:) と違うのは inout の後の第二引数があるかないかくらいな気がするけど・・・
01:36
演算子なのもよくないのかな・・・
Avatar
rintaro 26-Sep-17 01:39 AM
関数でも再現して、第二引数つけると 4.0 でも推論効くので、
Avatar
koher 26-Sep-17 01:39 AM
なるほど、単一引数のときに起こる問題なんですね・・・。
Avatar
rintaro 26-Sep-17 01:41 AM
3.2 と 4.0 で挙動違うとなると SE-110 https://github.com/apple/swift-evolution/blob/master/proposals/0110-distingish-single-tuple-arg.md 絡みの何かっぽいですね。
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
rintaro 26-Sep-17 02:12 AM
🙂 1
Avatar
norio_nomura 26-Sep-17 02:20 AM
4.0.1へ入る修正と入らない修正の判断基準ってどんな感じなんだろう
Avatar
omochimetaru 27-Sep-17 06:45 AM
片側レンジめっちゃいい
06:46
func parseImportDecl(tokens: ArraySlice<TokenSyntax>) throws -> (decl: ImportDecl, rest: ArraySlice<TokenSyntax>)? { var index = tokens.startIndex ... return (decl: ImportDecl(keywordIndex: keywordIndex - tokens.startIndex, nameIndex: nameIndex - tokens.startIndex, tokens: Array(tokens[..<index])), rest: tokens[index...]) }
(edited)
Avatar
rintaro 27-Sep-17 07:33 AM
Swift Parser!
Avatar
omochimetaru 27-Sep-17 07:33 AM
libSyntaxを使ってるんだけど
07:33
libSyntaxの実装が半端で
07:33
やりたいことやるにはちょっとたりないのでパーサーをでっちあげてる
👏 1
07:34
で、一応できたんだけど、Array + Int から ArraySliceにリファクタリングしてみていて
07:34
[...<index] [index...] で分割できて良い・・・ってなった
Avatar
omochimetaru 27-Sep-17 08:23 AM
うーん・・・ArraySliceだめだ・・・
08:24
indexを更新しないといけないケースで型が同じだから書き忘れちゃう
08:24
ダメというか今のシーンにはあってなかった
Avatar
omochimetaru 27-Sep-17 08:42 AM
Contribute to SwiftPack development by creating an account on GitHub.
08:42
結局Sliceやめちゃった
08:43
やっていて思ったんだけど、Swiftの構文は結構パースしやすいように意識されている?
Avatar
norio_nomura 28-Sep-17 01:54 AM
echo 'Dictionary(uniqueKeysWithValues: ["a","b","c"].enumerated())'|TOOLCHAINS=swift swiftc -swiftcがクラッシュする。
01:54
タプルのラベルって一致してないとダメなんだったっけ?
Avatar
omochimetaru 28-Sep-17 01:56 AM
クラッシュが再現した export TOOLCHAINS=org.swift.3020170918a
Avatar
norio_nomura 28-Sep-17 02:00 AM
Dictionary(uniqueKeysWithValues: ["a","b","c"].enumerated().filter { $1 != "a" })
もクラッシュ。
02:00
Dictionary(uniqueKeysWithValues: ["a","b","c"].enumerated().filter { $1 != "a" }.map { ($0, $1) })
でクラッシュ回避。
Avatar
rintaro 28-Sep-17 02:01 AM
.map { $0 } でもいけますね
Avatar
omochimetaru 28-Sep-17 02:01 AM
3> Dictionary(uniqueKeysWithValues: [(offset: 0, element: "a")]) $R2: [Int : String] = 1 key/value pair { [0] = { key = 0 value = "a" } }
02:01
これ自体はいける・・・
02:02
["a"].enumerated().makeIterator().next() の型は (offset: Int, element: String)? なので
Avatar
norio_nomura 28-Sep-17 02:02 AM
ラベルは関係ないのか。
Avatar
omochimetaru 28-Sep-17 02:02 AM
ラベル一致性とかは多分大丈夫で型検査も正しく動いてて
Avatar
rintaro 28-Sep-17 02:02 AM
Dictionary(uniqueKeysWithValues: ["a","b","c"].enumerated().lazy) は別の形でクラッシュ
Avatar
omochimetaru 28-Sep-17 02:03 AM
その先の動作系で何かが変?
Avatar
norio_nomura 28-Sep-17 02:05 AM
👍 1
👏 1
Avatar
norio_nomura 28-Sep-17 02:41 AM
Avatar
omochimetaru 28-Sep-17 02:42 AM
いつのまにかはえてた
Avatar
rintaro 28-Sep-17 02:42 AM
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
omochimetaru 28-Sep-17 02:43 AM
なるほど
Avatar
norio_nomura 28-Sep-17 11:49 PM
echo 'Dictionary(uniqueKeysWithValues: ["a","b","c"].enumerated())'|TOOLCHAINS=swift swiftc -でswiftcがクラッシュする。
swift-DEVELOPMENT-SNAPSHOT-2017-09-28-aで直った。
Avatar
omochimetaru 29-Sep-17 01:14 AM
👏
Avatar
koher 03-Oct-17 01:46 AM
↓この前話してたやつのChris Lattnerのコメント。
[swift-evolution] Idea: Public Access Modifier Respected in Type Definition The core team would only consider a refinement or change to access control if there were something actively broken that mattered for ABI stability. -Chris
Avatar
omochimetaru 03-Oct-17 01:47 AM
なんかそのスレでもう一回、Swift5のABI優先したいから無視で、みたいな
01:47
返事がついてたきがする
Avatar
koher 03-Oct-17 01:48 AM
このML、せめて各メールにMLページへのパーマリンク入れてくれたら対応するページ探すの簡単になるのに・・・。
Avatar
omochimetaru 03-Oct-17 01:48 AM
あー、週ごとに分断するの不便ですよね
Avatar
koher 03-Oct-17 01:48 AM
それも不便だけど、メール見てからリンク貼ろうとして探すの大変
Avatar
koher 05-Oct-17 01:58 AM
型システムバグってる気がする。
$ swift Welcome to Apple Swift version 4.0 (swiftlang-900.0.63.10 clang-900.0.36). Type :help for assistance. 1> class Animal {} 2> class Cat: Animal {} 3> let a: () -> Cat = { Cat () } a: () -> Cat = 0x00000001000c5590 $__lldb_expr7`closure #1 () -> __lldb_expr_3.Cat in __lldb_expr_6 at repl.swift:3 4> let b: () -> Animal = a b: () -> Animal = 0x00000001000c5590 $__lldb_expr7`closure #1 () -> __lldb_expr_3.Cat in __lldb_expr_6 at repl.swift:3 5> let c: () -> [Cat] = { [Cat()] } c: () -> [Cat] = 0x00000001000c5680 $__lldb_expr11`closure #1 () -> Swift.Array<__lldb_expr_3.Cat> in __lldb_expr_10 at repl.swift:5 6> let d: () -> [Animal] = c error: repl.swift:6:25: error: cannot convert value of type '() -> [Cat]' to specified type '() -> [Animal]' let d: () -> [Animal] = c ^ 6> let e: [Cat] = [Cat()] e: [Cat] = 1 value { [0] = { __lldb_expr_1.Animal = {} } } 7> e is [Animal] $R0: Bool = true
Avatar
omochimetaru 05-Oct-17 01:59 AM
Array<T> と Array<U> の間のサブタイピングは
01:59
本当のサブタイピングじゃない中途半端なやつって感じがしてる
Avatar
tarunon 05-Oct-17 01:59 AM
事実上のmap
Avatar
omochimetaru 05-Oct-17 02:00 AM
代入可能だし is は 真になるのに、関数型に組み込まれたときはその互換性が発揮されない
Avatar
koher 05-Oct-17 02:00 AM
class Animal {} class Cat: Animal {} let a: () -> Cat = { Cat () } let b: () -> Animal = a // OK let c: () -> [Cat] = { [Cat()] } let d: () -> [Animal] = c // NG: error: cannot convert value of type '() -> [Cat]' to specified type '() -> [Animal]' let e: [Cat] = [Cat()] e is [Animal] // true
02:01
事実上のmap
確か前にここで確かめたときはこの場合でも CoW 効いててコピーは lazy だって話じゃなかったですっけ?
Avatar
tarunon 05-Oct-17 02:02 AM
そうそう
02:02
CoWの効いたmapみたいなそんな感じだったと思います
Avatar
koher 05-Oct-17 02:03 AM
これはSemaあたりのバグなのかな?
Avatar
omochimetaru 05-Oct-17 02:04 AM
バグ説だ
02:04
こういうの慣れてきてバグみ感じない
Avatar
koher 05-Oct-17 02:06 AM
let f: () -> Cat? = { Cat() } let g: () -> Animal? = f // OK
こっちはできたw
Avatar
omochimetaru 05-Oct-17 02:06 AM
草w
02:07
そういえば is の振る舞いって
02:07
OptionalとArrayだけ特別扱いで
02:07
自作のジェネリック型では無理ですよね?
Avatar
koher 05-Oct-17 02:10 AM
うん、今のところ。
02:10
↓壊れ方に一貫性はあるw
do { let a: (Animal) -> () = { _ in } let b: (Cat) -> () = a // OK } do { let a: ([Animal]) -> () = { _ in } let b: ([Cat]) -> () = a // error: cannot convert value of type '([Animal]) -> ()' to specified type } do { let a: (Animal?) -> () = { _ in } let b: (Cat?) -> () = a // OK }
Avatar
omochimetaru 05-Oct-17 02:11 AM
contravariance側でも同じかw
Avatar
koher 05-Oct-17 02:13 AM
do { let a: () -> () -> Cat = { { Cat() } } let b: () -> () -> Animal = a // OK } do { let a: () -> () -> [Cat] = { { [Cat()] } } let b: () -> () -> [Animal] = a // error: cannot convert value of type '() -> () -> [Cat]' to specified type '() -> () -> [Animal]' } do { let a: () -> () -> Cat? = { { Cat() } } let b: () -> () -> Animal? = a // OK }
02:14
関数もOKなので
02:14
Array だけ壊れてるみたい
Avatar
omochimetaru 05-Oct-17 02:15 AM
おお
Avatar
koher 05-Oct-17 02:17 AM
↓こういうのはOKっぽい
do { let a: [String: Cat] = ["": Cat()] let b: [String: Animal] = a // OK } do { let a: [String: [Cat]] = ["": [Cat()]] let b: [String: [Animal]] = a // OK } do { let a: [String: Cat?] = ["": Cat()] let b: [String: Animal?] = a // OK }
Avatar
omochimetaru 05-Oct-17 02:17 AM
マジか!
Avatar
norio_nomura 05-Oct-17 02:18 AM
as, is をoperatorにしてユーザーが定義できる様にして欲しくなる話だね。
Avatar
omochimetaru 05-Oct-17 02:19 AM
それでもコンパイラの代入チェックのときには動かないような?
02:20
実行時はas/isが書き換えられればいいけど、代入文の型検査時は静的だから書き換えたisが評価できない
Avatar
koher 05-Oct-17 02:21 AM
do { let a: () -> [String: Cat] = { ["": Cat()] } let b: () -> [String: Animal] = a // error: cannot convert value of type '() -> [String : Cat]' to specified type '() -> [String : Animal]' }
Avatar
norio_nomura 05-Oct-17 02:26 AM
代入文の型検査時は静的だから書き換えたisが評価できない
func as(lhs: A) -> Bの有無で決まるとか?
(edited)
Avatar
omochimetaru 05-Oct-17 02:29 AM
おー asの有無で制御してisはasの有無で自動生成だといけそうですね
Avatar
tarunon 05-Oct-17 02:35 AM
as書けるようになる時に、ジェネリクスの指定でサブタイプ指せるようになったら
02:36
ジェネリクスの共編性をそっち側で表現できるかな
02:37
func as<T, U>(_ v: My<T>) -> My<U> where U: T
こういうの。無くても出来るかな?
Avatar
omochimetaru 05-Oct-17 02:42 AM
as自体に型パラ取ってそうやれば変性をしばれそうだね
02:42
ジェネリック型の変性は C# 形式のdeclaration-siteで class Box<out T> とかやるのが楽だしわかりやすいとは思うけど
Avatar
tarunon 05-Oct-17 02:43 AM
scalaの+-は解りやすくて好き
02:45
swift、共編性やる気無さそうだしas拡張が先に来て、ワークアラウンドをツミツミすることになるなぁ
Avatar
koher 05-Oct-17 02:46 AM
前のジェネリック値型の自動共変、問題になるのはクラスが絡んだときだったから、値型に閉じた世界なら実現できそうな気がする。
02:46
C# のジェネリック値型がどうなってるのかずっと気になってる
Avatar
hironytic 05-Oct-17 02:48 AM
値型は継承できなかった気が。。。
Avatar
koher 05-Oct-17 02:49 AM
前に↓読んだときには値型だけ特別視されてた気がする。その頃はJavaについて調べてただけだったから、読み飛ばしたけど。 https://blogs.msdn.microsoft.com/ericlippert/2009/12/03/exact-rules-for-variance-validity/
I thought it might be interesting for you all to get a precise description of how exactly it is that we determine when it is legal to put “in” and “out” on a type parameter declaration in C# 4. I’m doing this here because (1) it’s of general interest, and (2) our attempt to make...
02:50
@hironytic 値型自体は継承できませんが、 Swift でいう↓みたいなのを作ったときの話ですね。
struct Box<T> { let value: T }
02:50
この T についての変性をどう扱うのかが気になってます。
Avatar
hironytic 05-Oct-17 02:50 AM
ああ、そっちが値型
Avatar
omochimetaru 05-Oct-17 02:51 AM
Swiftの値型って一箇所書き換えるのが全体書き換えだから T は常に out 扱いでうまくいかないんですっけ?
02:51
あいや、メソッド引数の方に受けてればoutとは限らんか
Avatar
koher 05-Oct-17 02:51 AM
ジェネリック値型を作れる&declaration-site variance annotationな言語がC#しか思いつかない
02:51
@omochimetaru 参照型と組み合わせたときに罠がある話を昔 @rintaro さんがしてた。
02:52
rintaro - 04/18/2017 この辺の話(Ty<Some> から Ty<Covariant> への変換) って https://devforums.apple.com/thread/261699 で語られているんですが、 https://devforums.apple.com/message/1102432#1102432 のArrayとかは出来るけど任意の value type には当てはまらないって文脈で > this doesn't apply to every value type (because value types can contain references and not enforce copy-on-write) らしいのですが、どういうケースなんでしょう?
02:53
↑あたりの会話
02:53
"Covariant" で検索
Avatar
omochimetaru 05-Oct-17 02:54 AM
リンク先なんか見れないな
Avatar
koher 05-Oct-17 02:54 AM
↑の発言の後で「わかった!」みたいなのがあったはず。
02:55
検索してJumpして前後を見るのが早いと思う
Avatar
tarunon 05-Oct-17 02:58 AM
前に @rintaro が成り立たない場合あるよ~みたいなことおっしゃってませんでしたっけ
Avatar
koher 05-Oct-17 02:59 AM
はい、言ってました。それをおもちに伝えてるとこです。
03:00
ただ、値型に閉じてれば問題ないんじゃないかと思ってます。
03:00
(プロパティもすべて値型)
Avatar
omochimetaru 05-Oct-17 03:01 AM
検索して前後見たけどわからなかった 俺もそのときわかった感じになった記憶あるんだけど
Avatar
tarunon 05-Oct-17 03:24 AM
値型に閉じてればジェネリクスのout固定が成り立つ、ジェネリクス自体も値型に閉じてないと駄目じゃないですかね
03:25
でもジェネリクスを値型に限定することは今はできない
03:25
protocool Foo: classはできるけど、逆は出来ない。
Avatar
koher 05-Oct-17 03:25 AM
そうですね
03:26
値型限定ほしいですよねぇ・・・
Avatar
hironytic 05-Oct-17 04:15 AM
もし値型に閉じていたら、FenceとFarmの例はどうなるんでしょう?
Avatar
koher 05-Oct-17 04:23 AM
ちょっと参照型で何が悪かったのか覚えてないですが、インスタンスの共有が起こらなければ起こらない問題だった気がします。
Avatar
tarunon 05-Oct-17 04:24 AM
インスタンス共有されてると、Fence<Cow>にSheep型がこんにちはしちゃうみたいな感じだった気がする
Avatar
tarunon 05-Oct-17 04:31 AM
Javaって確かそんな感じで配列がぶっ壊れるみたいな話有りましたよね
Avatar
koher 05-Oct-17 04:32 AM
あります。
Avatar
hironytic 05-Oct-17 05:06 AM
「Farm が Generic なクラスを持ってたらだめってことでした。」で検索 > FenceとFarmの例
Avatar
rintaro 06-Oct-17 02:30 AM
昨日の Array のキャストの絡みで、こういうの
let a: [Int] = [] a is [String] // true
☠ 2
Avatar
omochimetaru 06-Oct-17 02:31 AM
あー実行時検査だから
02:31
あれ?でも [Int] とかってboxingしないメモリレイアウトじゃないんか??
02:32
アクセスの都度、静的に Int仮定してんのかな
Avatar
koher 06-Oct-17 02:33 AM
空だけ特別?
Avatar
tarunon 06-Oct-17 02:34 AM
unsafeBitCast([Int](), [String].self) これ動きそう
Avatar
rintaro 06-Oct-17 02:35 AM
要素ごとにキャスト試して、エラーのものが見つからなかったら成功みたいな感じなのかな
Avatar
omochimetaru 06-Oct-17 02:35 AM
1> var a: [Int] = [0,1,2,3] a: [Int] = 4 values { [0] = 0 [1] = 1 [2] = 2 [3] = 3 } 2> var b: [String] = a as! [String] Could not cast value of type 'Swift.Int' (0x1013e0430) to 'Swift.String' (0x1013e36f8). 2017-10-06 11:35:18.511301+0900 repl_swift[28561:24355268] Could not cast value of type 'Swift.Int' (0x1013e0430) to 'Swift.String' (0x1013e36f8). b: [String] = <extracting data from value failed> Execution interrupted. Enter code to recover and continue. Enter LLDB commands to investigate (type :help for assistance.) Process 28561 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGABRT frame #0: 0x00007fffc4cf5d42 libsystem_kernel.dylib`__pthread_kill + 10 libsystem_kernel.dylib`__pthread_kill: -> 0x7fffc4cf5d42 <+10>: jae 0x7fffc4cf5d4c ; <+20> 0x7fffc4cf5d44 <+12>: movq %rax, %rdi 0x7fffc4cf5d47 <+15>: jmp 0x7fffc4ceecaf ; cerror_nocancel 0x7fffc4cf5d4c <+20>: retq Target 0: (repl_swift) stopped.
02:36
このエラーメッセージが出るってことは、Arrayオブジェクト自体はメモリに Int型だよって情報を 持ってるように思う
02:36
それか Int じゃなくて要素ごとに AnyにBoxingされちゃってるかだけど・・・
02:36
流石にそれは無いと思うんだよなあ
Avatar
koher 06-Oct-17 02:37 AM
いや、たしか @rintaro さんの言うように全要素検査してた気がする。 Any にボクシングはない。
Avatar
omochimetaru 06-Oct-17 02:37 AM
全要素検査しようにも、Intはただの8バイトなので
02:37
それがIntであることがわからないはず
02:37
Array側でメタ情報として知ってないと。
Avatar
koher 06-Oct-17 02:38 AM
そこは持った上で全検査なのでは?
Avatar
omochimetaru 06-Oct-17 02:38 AM
AnimalからCatへのダウンキャストとかなら
02:39
それでうまくいくか
Avatar
koher 06-Oct-17 02:39 AM
class Animal {} class Cat: Animal {} let a: [[Cat]] = [[Cat()]] a is [[Animal]] // true
02:40
こういう複雑なのを考えたくないのかな?
02:40
でも型だけで判断できると思うんだけど。
Avatar
omochimetaru 06-Oct-17 02:40 AM
全検査の結果が正しくて、値型で個別検査できないケースは継承が無いからメタ情報だけで結論が出せて全検査をスキップ?
Avatar
koher 06-Oct-17 02:40 AM
何のために検査するんだろ??
Avatar
omochimetaru 06-Oct-17 02:40 AM
[Animal] から [Cat] へのダウンキャストは
02:40
要素が全部Catのときだけ成功するはず
02:40
Dogが混ざってるかどうかは静的にわからない
Avatar
koher 06-Oct-17 02:40 AM
あー、それが true になるんだっけ
02:41
そうか
02:41
is の検査と as の成功が一致してないといけないのか。
02:42
なので、 is はあくまでインスタンスをチェックしてるだけで式の型を調べているわけではないと。 (edited)
Avatar
tarunon 06-Oct-17 02:42 AM
let x = [Int]() as? [String] // Cast from [Int] to unrelated type [String] always fail, 但し x = []
02:42
クソワロタ
Avatar
omochimetaru 06-Oct-17 02:42 AM
式の型っていうのは静的検査のこと?
02:43
@tarunon それはおかしいね 空の時だけは成功するんだから
02:43
always failでコンパイルエラーはバグだ
Avatar
tarunon 06-Oct-17 02:43 AM
いや、warningですね
Avatar
omochimetaru 06-Oct-17 02:44 AM
warningならいっか・・・?
Avatar
tarunon 06-Oct-17 02:44 AM
x = []が🙅なきがする
Avatar
rintaro 06-Oct-17 02:44 AM
いや、成功しちゃだめだと思うw
Avatar
omochimetaru 06-Oct-17 02:45 AM
そもそも空の時にですか?
02:46
ああ、warningじゃなくてerrorじゃないとってことかな
Avatar
tarunon 06-Oct-17 02:46 AM
warningは良いけど、キャスト成功シちゃだめ
👍 1
02:46
つまりx = nilが正しい
02:46
でも実行時にArrayはメタ情報とか持ってないからこうなってるんだと思う
Avatar
omochimetaru 06-Oct-17 02:47 AM
持ってない派だ
02:47
そろそろソース見るか・・・
Avatar
tarunon 06-Oct-17 02:47 AM
そうするともしかして
Avatar
koher 06-Oct-17 02:47 AM
1> let a: [Int] = [] a: [Int] = 0 values 2> type(of: a) $R0: [Int].Type = [Int]
02:47
これは実行時情報じゃないってことですか?
02:49
1> let a: [Int] = [] a: [Int] = 0 values 2> type(of: a) $R0: [Int].Type = [Int] 3> func foo<T>(_ value: T) { 4. print(type(of: value)) 5. } 6> foo(a) Array<Int>
Avatar
tarunon 06-Oct-17 02:49 AM
あれ、メモリサイズ同じ構造体ぶち込んでキャストしたらうまくいくかもと思ったら弾かれた
02:49
うーん
Avatar
koher 06-Oct-17 02:50 AM
多分、キャストできるかどうかの判定を全要素がキャスト可能かで判定しているのがややこしい原因で
02:50
インスタンスとしての型で考えてないんだと思います。
02:50
でもそれって変な気がする・・・
02:52
let cats: [Cat] = [Cat()] let animals: [Animal] = cats
一瞬、↑みたいなケースで catsanimals にコピーされないからインスタンスの型という概念が成り立たないかと思ったけど、コピーされないのはあくまでバッファであって、インスタンス自体の領域は別だからやっぱりインスタンスの型で判断できる気がする。
02:52
あー、でもそうすると animals から catsas で戻せなくなるのか。 (edited)
02:53
戻せなくてもいい気がするけどなぁ。
02:53
Optionalisas もややこしくなるな・・・。
02:54
runtimeがObjC ではない 場合の、 Array の _Buffer がこのオブジェクトだけど
02:54
_EmptyArrayStorage って型もあって
02:54
そっちは
02:55
型パラがなくてstaticElementType がVoid.selfになってる
02:56
internal struct _ContiguousArrayBuffer<Element>は
02:56
空で初期化するときは↑のEmptyArrayStorageを内部で使う
02:57
要素数付きの未初期化(uninitialized memory) バッファを確保するinitは型月の_ContiguousArrayStorage<Element> を使う
🌜 1
02:59
final class _EmptyArrayStorage : _ContiguousArrayStorageBase { } final class _ContiguousArrayStorage<Element> : _ContiguousArrayStorageBase { }
02:59
↑共通の親クラスになってて struct _ContiguousArrayBuffer は、 _ContiguousArrayStorageBase を var _storageでもってる。
03:01
struct Array がAPI層で runtimeによってBufferの型を変える struct ArrayBuffer が 可変長バッファの制御をしてる実装の層 class ArrayStorage系 が実際の連続メモリを表現してるメモリの層で、空と型付きがあって、要素の型が取れる
03:03
Arrayのinit() では _Buffer のinit() を呼んでるから _EmptyArrayStorage になってそう
03:04
objc runtime の場合は、 ContiguousArrayBufferじゃなくて、 ArrayBufferが使われていて、 ArrayBufferは storage を持ってるので、 Array / Buffer / Storage の3層設計はおなじだけど
03:04
internal typealias _ArrayBridgeStorage = _BridgeStorage<_ContiguousArrayStorageBase, _NSArrayCore> Storageの型がこれになっていて
03:05
Storage の実装として BridgeStorage という概念が出てきて、 _NSArrayCore ・・・
03:05
心配になってきた
03:05
ちゃんとboxingしないでInt並べてるのか・・・?
03:07
// rawValue is passed inout to _isUnique. Although its value // is unchanged, it must appear mutable to the optimizer. @_versioned internal var rawValue: Builtin.BridgeObject
03:07
@_inlineable // FIXME(sil-serialize-all) public // @testable var nativeInstance: Native { @inline(__always) get { _sanityCheck(isNative) return Builtin.castReferenceFromBridgeObject(rawValue) } }
03:08
var objCInstance: ObjC { @inline(__always) get { _sanityCheck(isObjC) return Builtin.castReferenceFromBridgeObject(rawValue) } }
03:08
NativeとObjCは BridgeStorageの型パラメータで、
03:08
rawValueってフィールドに
03:08
どっちかの型のオブジェクトがぶちこまれて
03:08
分岐したりキャストしてなんかEitherっぽくなってる
03:09
internal typealias _ArrayBridgeStorage = _BridgeStorage<_ContiguousArrayStorageBase, _NSArrayCore>
で、左側が さっきの pure swift のときの Storage の _ContiguousArrayStorageBase だから、
03:09
大丈夫そうな気がする
03:09
ObjCから来たオブジェクトだとBridgeStorageのrawValueが右側の_NSArrayCoreになっていて
03:10
Swiftから来たオブジェクトだとrawvalueが左側のContiguousASBになっていると予想
03:10
あとはなんか as とかでObjC側にブリッジしたりするときにめんどくさいことが起こるんだろう・・・
Avatar
tarunon 06-Oct-17 06:15 AM
[Animal] as? [Cat] これを実現するためには、1要素毎にキャストして成功したらOKみたいな処理にする必要があって
06:15
Emptyだとキャストが発生しないから素通りしてしまってる、とか
Avatar
omochimetaru 06-Oct-17 06:15 AM
Emptyならキャストできるのは正しいんじゃない?
Avatar
tarunon 06-Oct-17 06:15 AM
いやそうじゃなくて
06:16
[Int] as? [String]
Avatar
omochimetaru 06-Oct-17 06:16 AM
.none は Optional<Int> でもあるし Optional<String> でもあるのと一緒で。
06:16
ああ その
06:16
バグの話か
Avatar
tarunon 06-Oct-17 06:16 AM
それキャストできていいの?
Avatar
omochimetaru 06-Oct-17 06:16 AM
俺はいいんじゃないかと思ってて。
Avatar
tarunon 06-Oct-17 06:16 AM
いや俺は駄目だと思う
Avatar
omochimetaru 06-Oct-17 06:16 AM
Arrayの「内部の型」は
06:17
あくまで効率化のためのメタ情報で
06:17
Arrayは本当に値のリストを抽象化してるなら
06:17
互換性がある方が正しい
Avatar
tarunon 06-Oct-17 06:17 AM
Optional<Int>.none as? Optional<String> これの結果は Optional<Optional<String>>であるはずで、その上で、Optional<Optional<String>>.noneになるはずだ
Avatar
omochimetaru 06-Oct-17 06:19 AM
うーんっとつまり
06:20
var a: [Int] = [] var b: [String] = [] print(a == b)
これで結論が出ると思ったらコンパイルエラーだったw
Avatar
rintaro 06-Oct-17 06:20 AM
型をロジックの一部として使うことはわりとあると思うんだけど、
func foo(x: Any) { switch x { case let strings as [String]: print("strings \(strings)") case let integers as [Int]: print("integers \(integers)") default: print("unknwon") } } let ints: [Int] = [] foo(x: ints)
これで strings 判定されちゃうことになるので、やっぱキャスト出来ちゃうと駄目だと思います。
(edited)
👀 1
Avatar
tarunon 06-Oct-17 06:21 AM
やばい
06:21
let x = [Int?.none, Int?.none, Int?.none] let y = x as? [String?] // [nil, nil, nil]
これもなかなか。
Avatar
omochimetaru 06-Oct-17 06:23 AM
func foo<T>(value: T, type: T.Type) { switch type { case is Array<String>.Type: print("strings \(value as! Array<String>)") case is Array<Int>.Type: print("integers \(value as! Array<Int>)") default: print("unknwon") } } let ints: [Int] = [] foo(value: ints, type: type(of: ints)) // integers []
(edited)
Avatar
tarunon 06-Oct-17 06:24 AM
Optionalを直接as?しようとすると怒られるので
func cast<T, U>(from: U) -> T? { return from as? T } let z: Int?? = cast(from: String?.none) switch z { case .none: print("a") case .some(.none): print("b") // ココ case .some(.some): print("c") }
で、やはりOptional.noneも同様にキャストが成功している。
Avatar
omochimetaru 06-Oct-17 06:24 AM
こうすべきなんじゃないか
Avatar
tarunon 06-Oct-17 06:25 AM
それを書け、というのは中々どうして厳しいと思うけど。普通に初見殺しだ
Avatar
omochimetaru 06-Oct-17 06:25 AM
あ、これtype: 消せるか
06:25
func foo<T>(value: T) { switch T.self { case is Array<String>.Type: print("strings \(value as! Array<String>)") case is Array<Int>.Type: print("integers \(value as! Array<Int>)") default: print("unknwon") } } let ints: [Int] = [] foo(value: ints)
06:26
うーんでも
06:26
「値的な特性としての互換性」をみとめないと
06:27
animals as! Array<Cat> のパターンが
06:27
認められないと思う
Avatar
tarunon 06-Oct-17 06:27 AM
個人的にはそれ今実装されてるけど認めてない存在なのでなんとも
Avatar
omochimetaru 06-Oct-17 06:28 AM
なるほど。
Avatar
tarunon 06-Oct-17 06:28 AM
そもそもArrayとOptionalの共変性、結構色んな所でボロが出てて酷い
Avatar
omochimetaru 06-Oct-17 06:28 AM
型だけでみれば Array<Animal> は一般にDogも飛び出してくるから
06:28
互換性が無いってのがいいね
06:28
なんかSwiftのキャストって
06:28
値の型がその型でもあるか
06:28
っていう意味じゃなくて
06:28
その型に変換できるかって意味な感じがする
Avatar
tarunon 06-Oct-17 06:29 AM
asの挙動としてはそう
Avatar
omochimetaru 06-Oct-17 06:29 AM
(型変換コンストラクタはなんなんだってなるけど
06:30
値変換性としてみた全体的な方向性は納得できて、おかしいのは、
var a: [Int] = [] var b: [String]? = a as? [String] // Cast from '[Int]' to unrelated type '[String]' always fails
この警告だけ
(edited)
06:31
あ・・・
06:33
わかった
06:33
func foo(_ x: Any) { switch type(of: x) { case is [String].Type: print("strings \(x as! [String])") case is [Int].Type: print("integers \(x as! [Int])") default: print("unknwon") } } var a: [Int] = [] foo(a) // integers []
(edited)
06:33
こうかくべきなんだ
Avatar
tarunon 06-Oct-17 06:33 AM
値型として考えたときにコピーで互換性さえあればいいでしょ、と言うのはそれはそれで成り立つかもしれないけど、だとするとクラスの型変換が同じ as で出来るのはおかしい。こっちは世界の崩壊を招く
Avatar
omochimetaru 06-Oct-17 06:33 AM
「オブジェクトの型」で分岐したいのか「is/as 互換性判定」で分岐したいのかが別
06:35
だとするとクラスの型変換が同じ as で出来るのはおかしい。こっちは世界の崩壊を招く
クラスの方は変換して新しいオブジェクトができちゃうと同一性が維持されないから無理で、
06:35
インスタンスの実際の型が互換性があるかでしかキャストされない (edited)
Avatar
tarunon 06-Oct-17 06:35 AM
let x = [Int?.none, Int?.none, Int?.none] x is [String?] // true type(of: x) is [String?].Type // false
06:35
これが正しい世界とは到底思えないんだけど
Avatar
omochimetaru 06-Oct-17 06:35 AM
そうかなあ 俺はスッキリしてきた
Avatar
tarunon 06-Oct-17 06:37 AM
じゃあこれもOKなの?
let x = [Int??.none, Int??.none, Int??.none] let y = x as? [Int?] // [nil, nil, nil]
Avatar
omochimetaru 06-Oct-17 06:37 AM
let x = [Int?.none, Int?.none, Int?.none] type(of: x) == [Int?].self // true
06:38
メタクラスの同値性で見れるから == でも書けるね、継承を区別したいときはこれが必要になる (edited)
Avatar
tarunon 06-Oct-17 06:38 AM
特定のケースに突入するとOptionalのtagged unionの特性が喪失するということと同義
Avatar
omochimetaru 06-Oct-17 06:39 AM
OKで、 as? の考え方が違うってだけだと思う
06:40
asってなんなんだ ドキュメント見てくる
06:42
subclassがうんぬんと書いてあった・・・
06:42
てかさっきの例で思ったんだけど
06:42
Anyってやっぱnominal typeじゃないから
06:42
元の値の型を保持してるんだな
06:42
どんな型の値でも保持できる型であって、Anyという特定の型じゃない
Avatar
tarunon 06-Oct-17 06:43 AM
全部のprotocol型変数がそうじゃないかしら
Avatar
omochimetaru 06-Oct-17 06:43 AM
だね protocol の Existentialがそう
06:43
Anyもちゃんとそれの仲間ってことが確認できた
Avatar
tarunon 06-Oct-17 06:43 AM
そもそもAnyってprotocol<>じゃなかったっけ
Avatar
omochimetaru 06-Oct-17 06:43 AM
それはそう
06:44
でもなんかそれ証拠ってどこにあるんだっけ
06:44
俺も知識としてはそれ知ってるんだけど。
Avatar
tarunon 06-Oct-17 06:44 AM
ヘッダーで見た気がするんだよなぁ
06:45
なかった。かわりに
06:45
/// If the dynamic type of `obj` doesn't implement a `getIntegerValue()` /// method, the system returns a runtime error when you initialize /// `certainValue`. /// /// Alternatively, if you need to test whether `obj.getIntegerValue()` exists, /// use optional binding before calling the method. /// /// if let f = obj.getIntegerValue { /// print("The value of 'obj' is \(f())") /// } else { /// print("'obj' does not have a 'getIntegerValue()' method") /// } /// // Prints "The value of 'obj' is 100" public typealias AnyObject
(edited)
06:45
お前なんのエイリアスなんや…
06:46
それちょうどみつけたよ
06:46
BuiltIn.AnyObject
06:46
public typealias AnyObject = Builtin.AnyObject public typealias AnyClass = AnyObject.Type
Avatar
tarunon 06-Oct-17 06:46 AM
stdlib特有のprivate(privateとは言っていない)だ
Avatar
rintaro 06-Oct-17 06:53 AM
昔は
typealias Any = protocol<>
が実際にあったけど、 & 記法になったタイミングで Any がキーワードになり、Parser で特別扱いになりました。
Avatar
omochimetaru 06-Oct-17 06:54 AM
ほーーー
Avatar
rintaro 06-Oct-17 06:56 AM
そのうち typealias Any = Builtin.Any になるかもしれないですね。
Avatar
tarunon 06-Oct-17 09:47 AM
Swift4からOptional同士のキャストもas?で書けるようになってた。3からいけたっけ?
let x = Int??.none as? Int? let y = Int?.none as? Int?? switch x { case .none: print("print") case .some: print("-") } switch y { case .none: print("-") case .some: print("print") }
(edited)
09:48
で、↑の非対称性が気になる
09:48
そもそも値の互換性というのが動的型付け言語っぽくって中々厳しい感情があるというのが
09:50
nn?
09:50
これはこれで問題ないのか
09:54
ああ、これですね
09:55
let x = [Int?.none] as? [Int??] switch x?.first! { case .none: print("x") // !! case .some(.none): print("y") case .some(.some): print("z") } let y = [Int?.none] as [Int??] switch y.first! { case .none: print("x") case .some(.none): print("y") // !! case .some(.some): print("z") }
(edited)
09:58
as? と asで挙動がかわるのもあった
09:59
bugs.swift.orgにあがってるかな。なければ後でまとめて書いておこう。
Avatar
omochimetaru 06-Oct-17 10:04 AM
すごいねそれw
10:04
as? の使用に対して警告だしながら > Conditional cast from '[Optional<Int>]' to '[Int??]' always succeeds
10:04
違う結果になるというw
Avatar
tarunon 06-Oct-17 10:14 AM
値互換、やろうとすると型システムの加護受けられないから、この手のバグが無限にでてくると思う
10:14
jsでどう見てもfalseなのがtrueになる問題が対岸の火事じゃなくなるよ
10:15
ああ、バグじゃなくて仕様になり得るのか
Avatar
tarunon 06-Oct-17 01:05 PM
検索(Covariantで)した感じあまり報告されてないっぽかったんで報告しようと思うんですが
13:05
これの他に特筆するやつありますかね
13:05
funciton周りとか?
Avatar
tarunon 06-Oct-17 05:31 PM
17:31
あった、これっぽい
17:32
てか報告者りんたろ先生じゃんw
Avatar
omochimetaru 10-Oct-17 04:39 PM
swift tweetsの原稿書いてたらLoEのバグを見つけた https://bugs.swift.org/browse/SR-6103
Avatar
norio_nomura 10-Oct-17 11:26 PM
もうSwift 4.0.1へ入れてもらえないと諦めていた修正が入りそうで嬉しい。 https://github.com/apple/swift/pull/12369
What's in this pull request? Cherry-picks #11315 to swift-4.0-branch. Explanation: Better resolves SR-5206 until the introduction of conditional conformance. As a temporary workaround for SR-5206, ...
🎊 3
Avatar
omochimetaru 11-Oct-17 01:28 AM
@norio_nomura 元々は SingleValueContainerの中にUnkeyedContainerが入っててその中にバイト値が1つずつ入ってたのを
01:29
Codable.swift と JSONEncoder.swift を改造することで SingleValueContainer に包む事がないようにした、って感じですか?
01:31
いや中に入ってるわけじゃなくて2種類のフローがあるのかな、うーん
Avatar
norio_nomura 11-Oct-17 01:37 AM
Encoder, Decoderはサポートする型により、Codable自身のコーディング表現をオーバーライドする様になってます。
01:42
例えばURLURL自身にエンコードさせると、["relative":"http://apple.com"]みたいな辞書表現になります。
Avatar
omochimetaru 11-Oct-17 01:43 AM
ふむふむ
01:44
On implementing Codable conformance, if it uses container.encode(_:…) instead of container.encodeIfPresent(_:…), container.encode(url, forKey: .url) produces dictionary. But, `JSONDecoder` tries to decode Optional<URL> from string.
Avatar
norio_nomura 11-Oct-17 01:44 AM
しかし、JSONEncoder"http://apple.com"として扱いたいので、EncodableURLだったらこうする、と特別扱いします。
Avatar
omochimetaru 11-Oct-17 01:49 AM
} else if T.self == URL.self { // Encode URLs as single strings. return self.box((value as! URL).absoluteString)
01:50
本当だ。
Avatar
norio_nomura 11-Oct-17 01:51 AM
Optional, Set, Arrayにこれらの型が入っていた場合にも特別扱いしなければいけないのですが、Conditional Conformanceがないため、Decodableのコードが素直にかけませんでした。
Avatar
omochimetaru 11-Oct-17 01:53 AM
あーこれそういうことか URL.swift の initの冒頭にあるのは、 文字列表現だったときのフローがまずあって、ダメだったら辞書表現をやってた
Avatar
norio_nomura 11-Oct-17 01:55 AM
Swift 4.0のextension Optional : Decodable
extension Optional : Decodable /* where Wrapped : Decodable */ { @_inlineable // FIXME(sil-serialize-all) public init(from decoder: Decoder) throws { // Initialize self here so we can get type(of: self). self = .none assertTypeIsDecodable(Wrapped.self, in: type(of: self)) let container = try decoder.singleValueContainer() if !container.decodeNil() { let metaType = (Wrapped.self as! Decodable.Type) let element = try metaType.init(from: container) self = .some(element as! Wrapped) } } }
(Swift 4.0のコードに変更)
(edited)
01:59
本当はDecoderの処理を優先して、こう書きたい。
let container = try decoder.singleValueContainer() if !container.decodeNil() { - let metaType = (Wrapped.self as! Decodable.Type) - let element = try metaType.init(__from: container) - self = .some(element as! Wrapped) + self = .some(try container.decode(Wrapped.self)) } } }
(edited)
02:05
Swift 4.0では、Standard Libraryで提供されるJSONEncoderとかのCoderで特別扱いされるURLの側で「JSONEncoderだったら辞書表現をやめる」みたいな力技で対応されていました。 https://github.com/apple/swift/pull/10766 (edited)
What's in this pull request? Addresses SR-5206 for JSONEncoder and JSONDecoder. One of the limitations of not having conditional conformance at the moment is that the implementation of init(from:) ...
Avatar
tarunon 11-Oct-17 02:07 AM
これだと任意のEncoder実装しても上手くいかなくなる
Avatar
norio_nomura 11-Oct-17 02:08 AM
そう、サードパーティのCoderではバグっていたのです。
02:09
これがSwift 4.0.1で直りそう、というお話。
Avatar
tarunon 11-Oct-17 02:09 AM
ウレシイ
Avatar
norio_nomura 11-Oct-17 02:14 AM
サードパーティのCoder実装がどれくらいあるのか知りませんが…
02:15
僕が書いてたYAMLCoder実装は未リリース。
Avatar
norio_nomura 12-Oct-17 09:38 PM
これがSwift 4.0.1で直りそう、というお話。
4.0.1に入るかどうか微妙な時期らしい…
Avatar
omochimetaru 17-Oct-17 06:53 AM
Slackから転載 @tarunon --- RxTestについての質問なのですが、Observable<Void>の送信をTestableObserverで検知したい場合
let results = scheduler.createObserver(Void.self) XCTAssertEqual(results.events, [next(0, ()), next(10, ())])
と書くとコンパイルエラーになってしまいます。 どのように書くと良いのでしょうか…? (そもそもObservable<Void>はTestableObserverでテストを書くべきでは無いのでしょうか…?)
Avatar
tarunon 17-Oct-17 06:54 AM
VoidってEquatableだっけ
Avatar
omochimetaru 17-Oct-17 06:55 AM
() == () // true
06:55
それは俺も試した
Avatar
rintaro 17-Oct-17 06:58 AM
== はあるけど Eqatable ではないんじゃないかな?
Avatar
tarunon 17-Oct-17 06:58 AM
next(0,())、これ.足りてない?
06:59
ああ、今はnextで書けるのか
06:59
バージョン欲しいな
Avatar
omochimetaru 17-Oct-17 07:00 AM
func f<X: Equatable>(x: X) {} f(x: ())
07:00
error: TempGround.playground:3:6: error: argument type '()' does not conform to expected type 'Equatable' f(x: ()) ^
07:00
ほんとだ。
Avatar
tarunon 17-Oct-17 07:00 AM
イや違うよね
Avatar
rintaro 17-Oct-17 07:01 AM
Nominal ではないので、プロトコル当てられないと思う。
Avatar
tarunon 17-Oct-17 07:01 AM
next(0,())って書けるのはRxSwiftのテストケースがRecorded+Timeless.swift持ってるから
Avatar
omochimetaru 17-Oct-17 07:02 AM
--- @omochimetaru ありがとうございます。nextはRecorderというRxTestのObserveイベントの型を生成するメソッドです。 let results = scheduler.createObserver(Bool.self) XCTAssertEqual(results.events, [next(0, true), next(10, false)]) のようにBoolでは正常にコンパイル出来るので、voidの比較は出来ないのかなぁと ---
Avatar
tarunon 17-Oct-17 07:02 AM
書いてあるのか
Avatar
omochimetaru 17-Oct-17 07:02 AM
Equatableじゃないことが原因っぽいなあ
Avatar
tarunon 17-Oct-17 07:03 AM
えーと
07:04
public func == (lhs: Recorded<Void>, rhs: Recorded<Void>) -> Bool { return lhs.time == rhs.time }
これその辺に書いたら何とかなりませんかね
Avatar
omochimetaru 17-Oct-17 07:05 AM
なるほどな
Avatar
tarunon 17-Oct-17 07:05 AM
上と加えてEvent<Void>も要るかも。風邪なので布団に戻ります。
Avatar
omochimetaru 17-Oct-17 07:06 AM
風邪だったの・・・・
Avatar
tarunon 17-Oct-17 07:57 AM
@omochimetaru なんでXCTAssertEqualがEquatableじゃないRecordedを引数に取れるんだ?と思ったら
07:57
XCTest+Rx.swift
07:58
ここに拡張されたXCTAssertEqualが入ってた。なんでここにVoidの拡張を付け足すのが正解。
Avatar
omochimetaru 17-Oct-17 07:58 AM
お、なるほど、他にもそうやってる場所があるのか
Avatar
tarunon 17-Oct-17 07:59 AM
ConditionalConformanceはよ案件だねぇ。
07:59
あとそもVoidがEquatableじゃないの、空タプルだから仕方ないとはいえ結構厳しい
Avatar
omochimetaru 17-Oct-17 07:59 AM
VoidはいかなるVoid同士で同一ということであってほしいね
08:00
ああまだタプル自体もEquatableじゃないのか
Avatar
tarunon 17-Oct-17 08:00 AM
ConditionalConformanceが実装されても
08:01
extension Void: Equatableが書けない限りはここに関して悲しみを繰り返すので
Avatar
omochimetaru 18-Oct-17 01:37 AM
どんなメタクラスでも入る型って書けないのかな?
01:37
AnyClass は typealias AnyClass = AnyObject.Type なんだけど
01:37
これだと class Cat {} ; struct Stone{} で Cat.self は代入できるけど、Stone.self は代入できない。
Avatar
tarunon 18-Oct-17 01:39 AM
Any.Type
01:39
だめかな?
Avatar
omochimetaru 18-Oct-17 01:40 AM
あ、それがうまくいかないと思ったけどそれでいけたわ ありがとう
01:44
メタクラス、Hashableになっていなくて、Dictionaryのキーにできない・・・
Avatar
tarunon 18-Oct-17 01:44 AM
ObjectIdentifier定期
Avatar
omochimetaru 18-Oct-17 01:44 AM
あ〜
Avatar
tarunon 18-Oct-17 01:45 AM
メタクラスは型毎にアドレスあるからいける
Avatar
omochimetaru 18-Oct-17 01:45 AM
メタクラスはシングルトン保証あるんだっけ
Avatar
tarunon 18-Oct-17 01:45 AM
クラス値と型
Avatar
omochimetaru 18-Oct-17 01:45 AM
完璧だ
01:45
定期スレだった
Avatar
t.ae 18-Oct-17 02:38 AM
import Foundation class A: Encodable { let f1: String init(f1: String) { self.f1 = f1 } } class B: A { let f2: String init(f1: String, f2: String) { self.f2 = f2 super.init(f1: f1) } } let b = B(f1: "f1", f2: "f2") let x = try JSONEncoder().encode(b) String(data: x, encoding: .utf8) // -> { "f1": "f1" }
(edited)
😭 1
02:38
今更Codable触り始めてるんですけどこんなもんなんですか?
Avatar
omochimetaru 18-Oct-17 02:39 AM
継承はうまくいかない
02:39
手動定義でいろいろやっていかないと。
Avatar
t.ae 18-Oct-17 02:40 AM
protocolにEncodable適用した場合もその型でencodeに渡すの無理みたいですね……
Avatar
omochimetaru 18-Oct-17 02:41 AM
protocolに適用した場合ってどうなるんだ? Encodable protocol自体は連鎖して引き継ぐと思うけど
02:42
いや、それでも自動生成されるはずじゃない? Codable protocol は Encodable & Decodable だから
Avatar
t.ae 18-Oct-17 02:43 AM
protocol C: Encodable { var f3: String { get } } struct D: C { var f3: String } let d: C = D(f3: "f3") let y = try JSONEncoder().encode(d) // ここでコンパイルエラー
(edited)
02:43
Dとして渡すと通ります
Avatar
omochimetaru 18-Oct-17 02:43 AM
Cのまま渡すってことか
Avatar
t.ae 18-Oct-17 02:47 AM
protocolでやるならCencodeメソッドを足してDや各々でエンコードってのが良さそうですかね
Avatar
omochimetaru 18-Oct-17 02:48 AM
/// A type that can encode itself to an external representation. public protocol Encodable { /// Encodes this value into the given encoder. /// /// If the value fails to encode anything, `encoder` will encode an empty /// keyed container in its place. /// /// This function throws an error if any values are invalid for the given /// encoder's format. /// /// - Parameter encoder: The encoder to write data to. func encode(to encoder: Encoder) throws }
02:48
型的にはなんでダメなのか謎だな
02:49
そこでencodeメソッド手動で足すとどうなるんだ?w
Avatar
t.ae 18-Oct-17 02:50 AM
protocol C: Encodable { var f3: String { get } func encode() throws -> Data } struct D: C { var f3: String func encode() throws -> Data { return try JSONEncoder().encode(self) } } let d: C = D(f3: "f3") let y = try d.encode()
02:51
こんなつもりでしたが
02:51
encode実装が個々に必要になるのが難点 (edited)
Avatar
omochimetaru 18-Oct-17 02:51 AM
open func encode<T : Encodable>(_ value: T) throws -> Data {
02:51
JSONEncoder側の <T: Encodable> が
02:51
このTって自動生成のerasureは適用できないんだっけ。
02:53
protocol P {} class Cat : P {} func f<X: P>(_ p: X) {} var a: P = Cat() var b: Cat = Cat() f(a) // NG f(b) // OK
02:53
やっぱそうだ
02:53
さっきのCがダメな理由はこれ↑
Avatar
t.ae 18-Oct-17 03:00 AM
C のextensionにencode書けばいいのか。
03:02
protocol C: Encodable { var f3: String { get } func encode() throws -> Data } extension C { func encode() throws -> Data { return try JSONEncoder().encode(self) } } struct D: C { var f3: String } let d: C = D(f3: "f3") let y = try d.encode()
これがいける?
Avatar
omochimetaru 18-Oct-17 03:09 AM
encode() って名前の意味が変わっちゃっててわかりにくいし、 JSONEncoderを使う事が埋め込まれてるから、 toJSON() -> Data という名前の方が良さそう
🙆 1
Avatar
t.ae 18-Oct-17 03:27 AM
うーん軽く調べた限りではOptional.noneは常にフィールド自体省略になってnullにすることができない気が……
03:31
fileprivate func box<T : Encodable>(_ value: T) throws -> NSObject { return try self.box_(value) ?? NSDictionary() }
Container上では
03:32
うーんいったりきたりしててよくわかrなn
03:32
public mutating func encodeNil() throws { self.container.add(NSNull()) }
03:32
こんなのもあるけどね
03:33
return try JSONSerialization.data(withJSONObject: topLevel, options: writingOptions)
03:33
↑ここで消えてるのか、それとも、コンテナ構造の時点で消えてるのか?
Avatar
norio_nomura 18-Oct-17 03:40 AM
コンパイラが生成するencode(to:)だとそうなりますね。
Avatar
omochimetaru 18-Oct-17 03:40 AM
あ、そこで消えるのか!
03:41
じゃあ、encode(to:)を手動で書いて、encodeNilを明示的に使うようにしたら、挙動を変えられるんですね。
03:41
コンパイラが生成するencode(to:)も合わせてコードを追跡しないと全容がわからないのがなかなか悩ましいな 便利だけど
Avatar
norio_nomura 18-Oct-17 03:48 AM
OptionalだとencodeIfPresent(_:forKey:)が使われるコードが生成される。これをencode(_:forKey:)を使うコードを自分で書けばnullが使われる。 https://github.com/apple/swift/blob/master/lib/Sema/DerivedConformanceCodable.cpp#L623-L624 (edited)
swift - The Swift Programming Language
Avatar
omochimetaru 18-Oct-17 03:49 AM
おおー これ読むと面白そう
03:50
C++内部のSwiftコード生成APIだ
Avatar
t.ae 18-Oct-17 03:50 AM
Codable使う旨味が減っちゃいますねぇ。 Optional.noneのあつかいもstrategyで書けたらいいんじゃないかと思うんですが データ全体じゃなく部分ごとにここは省略したいとかある可能性もあるんで微妙ですかね
Avatar
omochimetaru 18-Oct-17 03:51 AM
そういう場合はOptionalを使わずに自分でモナド用意すれば?
Avatar
t.ae 18-Oct-17 03:51 AM
それが無難ですかねやっぱり
Avatar
omochimetaru 18-Oct-17 03:51 AM
Codableの旨味を最大化したいならそれがいいとおもう
03:51
標準のOptionalはキーが消えるものとして諦めて、捨てる
03:52
別に、computed property で Optional な get / set を作っとけば
03:52
使い勝手は変わらないし。
Avatar
tarunon 18-Oct-17 04:14 AM
struct Foo: Encodable { var optionalInt: Int? private struct FooEncode: Encodable { var optionalInt: KeyedOptional<Int> /* Foo <-> FooEncode 変換書く */ } func encode() throws -> Data { return FooEncode(self).encode() } }
こげな
04:14
って考えたんだけど、変換書いてる部分がencode自動生成に相当するのであんまうま味ないですね
Avatar
d_date 18-Oct-17 04:15 AM
Codableサボりたい方へ。 https://swift.quicktype.io
Avatar
omochimetaru 18-Oct-17 04:15 AM
JSONが先なのか
04:16
べんりそう
Avatar
tarunon 18-Oct-17 04:16 AM
こういうの見るといじめたくなってしまう
Avatar
omochimetaru 18-Oct-17 04:16 AM
www
Avatar
d_date 18-Oct-17 04:16 AM
quicktype - Quick types from data
Avatar
tarunon 18-Oct-17 04:18 AM
普通にかしこくて腰抜かした
😇 1
Avatar
d_date 18-Oct-17 04:19 AM
w
Avatar
tarunon 18-Oct-17 04:19 AM
無茶苦茶な型を与えるとちゃんとenum使って分岐してくれる、すごいねこれ
Avatar
omochimetaru 18-Oct-17 04:20 AM
へ〜〜〜〜!
Avatar
tarunon 18-Oct-17 04:21 AM
{ "objects": [ { "key": 1, "value": "foo" }, { "key": "2", "value": "bar" } ] }
こういう意地悪すると、
enum Key: Codable { case int(Int) case string(String) }
こんなのが生える
Avatar
d_date 18-Oct-17 04:23 AM
そうそう、Optionalの判定もしてたはず
04:25
{ "objects": [ { "key": 1, "value": "foo" }, { "key": null, "value": "bar" } ] }
で、
struct Object: Codable { let key: Int? let value: String }
(edited)
👏 1
Avatar
norio_nomura 18-Oct-17 01:01 PM
NSDictionaryからDataを経由せずに直接デコードしたい…
☝ 2
Avatar
ikesyo 18-Oct-17 01:39 PM
遅レスですが、Codableで継承は基本的にsuperclass, subclassともに手で書くことになると思ってます。subclassの実装書く時にはsuperEncoder/superDecoder使うと感じで。 (edited)
13:40
継承が使えないわけではなくて、一応仕組みは用意されてる。
13:42
JSONDecoderがDataしか受け付けないの、やっぱり扱いづらいですよね(他との相互運用性的に) (edited)
Avatar
norio_nomura 18-Oct-17 11:19 PM
superEncoder/superDecoderの利用は必須ではないですね。superclassのデータをキーsuperに入れるかどうかはユーザー次第になってるかと。
Avatar
t.ae 19-Oct-17 12:26 AM
public class Comprehensive: Encodable { private let field1: String private let field2: String? private let field3: String? fileprivate init(field1: String, field2: String?, field3: String?) { self.field1 = field1 self.field2 = field2 self.field3 = field3 } } public class Child1: Comprehensive { public init(field1: String, field2: String) { super.init(field1: field1, field2: field2, field3: nil) } } public class Child2: Comprehensive { public init(field1: String, field3: String) { super.init(field1: field1, field2: nil, field3: field3) } }
めちゃくちゃ汚いですがこれでやりたかったことはできそうです
00:30
pythonでサーバー/クライアント書かれてるところにswiftクライアント作ろうとしてるんですがjsonの扱いが自由すぎて分析が大変……
Avatar
omochimetaru 19-Oct-17 12:32 AM
型付けしなければベタ移植できるのでは?
Avatar
t.ae 19-Oct-17 12:32 AM
型付けしたい願望
Avatar
tarunon 19-Oct-17 12:33 AM
型付けしないならパイソンでいいでしょw
Avatar
omochimetaru 19-Oct-17 12:33 AM
あと、スキーマ定義とかどっかにないのか
00:34
パイソンのデコーダソースだけから目で復元するのはやばそう
Avatar
t.ae 19-Oct-17 12:34 AM
無さそうなんですねこれ……
Avatar
omochimetaru 19-Oct-17 12:35 AM
あ、デコーダよりエンコーダの方が構造わかりそう
Avatar
t.ae 19-Oct-17 12:36 AM
元のAPIはdictに何もかも詰め込んで放り投げてます
Avatar
omochimetaru 19-Oct-17 12:37 AM
そこのコードから構造が読み取れそう
Avatar
omochimetaru 19-Oct-17 02:23 AM
@ikesyo の ---
型パラメータをサブクラスで持って、親クラスではもたないと、型パラメータ部分を消せる
ちょうどKeyPathのクラス階層がそんな感じな気がする。ルートがAnyKeyPathで、そこからPartialKeyPath<Root>, KeyPath<Root, Value>みたいな。 https://developer.apple.com/documentation/swift/key_path_expressions --- これ、ウェブだとよくわからなかったのでXcodeからコピペ↓
public class AnyKeyPath {} public class PartialKeyPath<Root> : AnyKeyPath {} public class KeyPath<Root, Value> : PartialKeyPath<Root> {} public class WritableKeyPath<Root, Value> : KeyPath<Root, Value> {} public class ReferenceWritableKeyPath<Root, Value> : WritableKeyPath<Root, Value> {}
(edited)
02:23
話題キープ
06:49
AnyObjectにキャストすればresponds(to:)とか使えるという話
06:50
import Foundation class Cat { @objc func eat() {} } (Cat() as AnyObject).responds(to: #selector(Cat.eat)) // true
06:50
こんな感じで。
Avatar
omochimetaru 22-Oct-17 06:56 AM
Linux SwiftだとObjC Runtimeが無くてできなそう
Avatar
tarunon 22-Oct-17 07:01 AM
Foundation importすると使える裏技
Avatar
omochimetaru 22-Oct-17 07:04 AM
これって
07:04
#selector(Cat.eat) ってやってるけど
07:05
class Dog { @objc func eat() {} }
07:05
に対してもtrueなのか?
07:05
ObjC的にはセレクタになるときに "Cat" 性は落ちてるから
07:05
Dog.catも #selector(Cat.eat)でヒットしそう。
Avatar
tarunon 22-Oct-17 07:05 AM
それはそう
Avatar
omochimetaru 22-Oct-17 07:07 AM
ダックタイピングができるね
Avatar
tarunon 22-Oct-17 07:09 AM
eatに@objcがついてないと当然Selectorは生えないのでfalseになる
Avatar
omochimetaru 22-Oct-17 07:09 AM
- (oneway void)release;
07:09
おもしろいアトリビュートついてる
Avatar
tarunon 22-Oct-17 07:34 AM
oneway
Avatar
omochimetaru 22-Oct-17 07:34 AM
多分レシーバが使用不能になるとか
Avatar
tarunon 22-Oct-17 07:37 AM
これつまりSwiftのオブジェクトを、MRCのObjective-Cでも相互利用できるってことかな
Avatar
omochimetaru 22-Oct-17 07:37 AM
@objc class になってればできると思う
Avatar
norio_nomura 24-Oct-17 01:30 AM
Codableに準拠した型のletプロパティは、エンコードはされるけどデコードされることはないのね。
01:32
letプロパティをエンコードされない様にするには、letプロパティを含まないCodingKeysを用意すると。
Avatar
norio_nomura 24-Oct-17 01:40 AM
あいや、デフォルト値を持つletプロパティだ。
Avatar
tarunon 24-Oct-17 01:40 AM
デフォ値無しなら復元出来ますよね?
Avatar
norio_nomura 24-Oct-17 01:41 AM
ですね。
Avatar
norio_nomura 24-Oct-17 03:28 AM
SE-0182 String Newline Escaping を読むとsingle lineでも使えると書かれてるけど、実際には使えない? https://github.com/apple/swift-evolution/blob/master/proposals/0182-newline-escape-in-strings.md
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
rintaro 24-Oct-17 03:29 AM
使えないです。Rationale に記載されております。 < single line (edited)
Avatar
norio_nomura 24-Oct-17 03:31 AM
なるほど、ありがとうございます。 🙏
Avatar
norio_nomura 24-Oct-17 04:35 AM
リリースタグはついてないけど、4.0.1と4.0.2はApple内部で存在しているのだろうか。 https://github.com/apple/swift/commit/1ba634302805b92f505cc3b87047aeccadc8dcf7
Avatar
norio_nomura 24-Oct-17 06:56 AM
NSDictionaryからDataを経由せずに直接デコードしたい…
作った。 https://github.com/norio-nomura/ObjectEncoder
ObjectEncoder - Swift Encoders implementation using [String: Any], [Any] or Any as payload.
06:57
import Foundation import ObjectEncoder // single value let string = "Hello, ObjectEncoder" let encodedString = try ObjectEncoder().encode(string) (encodedString as AnyObject).isEqual(to: string) // true let decodedString = try ObjectDecoder().decode(String.self, from: encodedString) // dictionary struct S: Codable { let p1: String } let s = S(p1: "string") guard let encodedS = try ObjectEncoder().encode(s) as? [String: Any] else { fatalError() } encodedS["p1"] // "string" let decodedS = try ObjectDecoder().decode(S.self, from: encodedS) decodedS.p1 // "string" // array let array: [S] = [s, s] guard let encoded = try ObjectEncoder().encode(array) as? [[String: Any]] else { fatalError() } encoded[0]["p1"] // "string" let decoded = try ObjectDecoder().decode([S].self, from: encoded) decoded[0].p1 // "string"
Avatar
omochimetaru 24-Oct-17 06:57 AM
おお?
06:58
Codableのencodeメソッドはどうなるんです?これだと。
Avatar
norio_nomura 24-Oct-17 06:58 AM
JSONEncoderPropertyListEncoderみたいに、各型についての特殊な処理が一切入っていないCoders実装になってます。
06:59
[String: Any[Any]へそのまま突っ込むイメージ。
Avatar
omochimetaru 24-Oct-17 07:00 AM
あ、逆だ、勘違いsてた
07:00
Codableはエンコード形式を特に規定していなくて
07:01
JSONEncoderだからDataが最終的にやりとりされているだけか。
07:01
ObjectEncoderだからAnyなどが出てくるんですね
Avatar
tarunon 24-Oct-17 07:01 AM
なるほど
07:02
普通にお世話になりそうだw
07:02
JSONオブジェクトとしかやりとりしない品のないOSSめっちゃありますからね (edited)
07:03
G○○gle製とかFaceb○○k製とか
Avatar
norio_nomura 24-Oct-17 07:03 AM
利用イメージとしては
let source = CGImageSourceCreateWithURL(url as CFURL, nil), let properties = CGImageSourceCopyPropertiesAtIndex(source, 0, nil) as NSDictionary? let decoded: ImageProperties = try ObjectDecoder().decode(from: properties)
みたいなAPIからNSDictionaryで返ってきたデータのモデリング。
(edited)
07:05
に、使えるはず…
Avatar
omochimetaru 24-Oct-17 07:06 AM
ああ、それ系のカオスなオブジェクトw
Avatar
norio_nomura 24-Oct-17 07:14 AM
JSONEncoderPropertyListEncoderData以外も受け付けるAPIを作ってPR出すことも考えたけど、変換部分が邪魔だった。
Avatar
d_date 26-Oct-17 05:14 AM
Optional<URL>の関連ネタなんですけど、
{ “id”: 1, “url”: “” }
というAPIのレスポンスがあったとして、
struct Hoge: Codable { let id: Int let url: URL? }
これでデコードしようとすると、Invalid URL StringということでdataCorrupted扱いになります。このとき、urlをnilで取り扱うためのワークアラウンド、どなたかお持ちですか?
(edited)
Avatar
tarunon 26-Oct-17 05:15 AM
"url": "" がウソなのでそっち修正したいなぁ
Avatar
d_date 26-Oct-17 05:16 AM
それな
Avatar
takasek 26-Oct-17 05:16 AM
まあでも "url": null でも同じことなりませんか
Avatar
d_date 26-Oct-17 05:16 AM
そうなの?
Avatar
tarunon 26-Oct-17 05:16 AM
その場合はちゃんとURL?.noneとしてデコードできます
Avatar
d_date 26-Oct-17 05:17 AM
よかった
Avatar
takasek 26-Oct-17 05:17 AM
あ、そうですっけか
Avatar
tarunon 26-Oct-17 05:18 AM
生のURLはムリな気がする、ウソもデコードできるURL型を自分で定義するしか無いんじゃないかな
Avatar
takasek 26-Oct-17 05:18 AM
urlキーがない場合は自前でdecodeIfPresent書かなきゃいけないだけか
Avatar
omochimetaru 26-Oct-17 05:18 AM
struct Hoge: Codable { let id: Int let jsonUrl: String? var url: URL { get { ... } set { ... } } }
05:18
こうしておいて、jsonUrl の CodingKeyを "url" にさせる
05:18
とかってできるっけ
Avatar
tarunon 26-Oct-17 05:18 AM
Codable周りのコード全部自分で書けば出来る
05:19
struct Landmark: Codable { var name: String var foundingYear: Int var location: Coordinate var vantagePoints: [Coordinate] enum CodingKeys: String, CodingKey { case name = "title" case foundingYear = "founding_date" case location case vantagePoints } }
05:19
他のキーも定義しないといけなくなっちゃうけど・・・
05:19
Codable全部書くよりはマシにできる
Avatar
d_date 26-Oct-17 05:21 AM
たしかに、別なComputed Propertyで回避すればいいか。CodingKeysは俺の場合はQuicktypeで生えてるから、すぐいけそう。
Avatar
tarunon 26-Oct-17 05:21 AM
CodingKeyだけ定義できるのか
Avatar
omochimetaru 26-Oct-17 05:22 AM
Computed Propertyのgetterで 空文字列なら nil に変換する。 (edited)
Avatar
takasek 26-Oct-17 05:26 AM
struct Hoge: Codable { let id: Int private let jsonUrl: String? var url: URL? { return URL(string: jsonUrl) } enum CodingKeys: String, CodingKey { case id case jsonUrl = "url" } }
(edited)
Avatar
omochimetaru 26-Oct-17 05:27 AM
struct Hoge: Codable { let id: Int private let jsonUrl: String? var url: URL? { return jsonUrl.flatMap(URL.init) } enum CodingKeys: String, CodingKey { case id case jsonUrl = "url" } }
(edited)
05:28
あー、不正ならそのままでいのか
Avatar
takasek 26-Oct-17 05:31 AM
nilになる条件確認してみたけど空文字のときだけか
Avatar
banjun 26-Oct-17 05:31 AM
"日本語" とか
Avatar
takasek 26-Oct-17 05:31 AM
ほんとだ
Avatar
tarunon 26-Oct-17 05:31 AM
URL、確か怠け者なのでpunycodeとかクエリがデコード済みだとnilです
Avatar
omochimetaru 26-Oct-17 05:32 AM
URL(string: "httttttp::::////aaaaa")
↑いけた
😂 1
Avatar
tarunon 26-Oct-17 05:32 AM
punycodeやクエリがデコード済みでもURLにできる勤勉なメソッドも存在します(privateに)
05:32
まじでゆるさんからな~~~
Avatar
banjun 26-Oct-17 05:37 AM
struct Hoge: Codable { let id: Int let url: String? } extension Hoge { var urlurl: URL? {return url.flatMap {URL(string: $0)}} }
Codableがjsonをそのままうつしていると考えればこう
(edited)
Avatar
takasek 26-Oct-17 05:38 AM
url: Stringimage: UIImageView と同じレベルでやめたい
Avatar
omochimetaru 26-Oct-17 05:38 AM
お、それだとCodingKeyの修正が要らないですね。モデル利用側では url のほうを使わずに urlurl を使うのが注意点か
Avatar
tarunon 26-Oct-17 05:39 AM
JSONと直接変換するモデルとプログラムに使うモデル切り分けるのがいいのではという気がしている
Avatar
Kishikawa Katsumi 26-Oct-17 05:39 AM
url: String は合理的だと思いますよ。 URL オブジェクトはデータ構造というよりはユーティリティ。
Avatar
tarunon 26-Oct-17 05:40 AM
struct _Hoge: Codable { 略 }struct Hoge { 略 } でこいつら相互変換可能に。
Avatar
omochimetaru 26-Oct-17 05:40 AM
@Kishikawa Katsumi 何かパス加工などをするときに都度都度生成する方がいいってことですか?
Avatar
hiragram 26-Oct-17 05:40 AM
JSONと直接変換するモデルとプログラムに使うモデル切り分けるのがいいのではという気がしている
まさにやろうとしてる
Avatar
takasek 26-Oct-17 05:40 AM
なるほど<切り分ける
Avatar
Kishikawa Katsumi 26-Oct-17 05:40 AM
はい。URLのパスに関する操作が必要なときにオンデマンドで使えばいいと思います。もちろんURLで素直に受け渡しができるならそれでいいと思います。
Avatar
tarunon 26-Oct-17 05:40 AM
きみたちViewとViewModel切り分けるの得意でしょ
Avatar
banjun 26-Oct-17 05:41 AM
extension Hogeをtargetted extensionにしてカッコイイ名前つければ、hoge.カッコイイ名前.url になるのでは
Avatar
omochimetaru 26-Oct-17 05:41 AM
フーム そのスタイルはあんまり考えたことなかったけど、 URL型はどうせガバガバだしありな気もします
Avatar
hiragram 26-Oct-17 05:41 AM
Hogeモデルのインナー型にRawみたいな構造体作ってJSON構造そのままマッピングしてアプリ内で使うやつはHogeにvar fuga: String { return raw.fuga }とかしてる
Avatar
tarunon 26-Oct-17 05:42 AM
targetted extensionはアリな気がしてきた
05:42
codable、private propertyでも動きますよね
Avatar
omochimetaru 26-Oct-17 05:42 AM
@hiragram インナー型で HogeHoge.JSON にするの良さそう
05:43
ただわける系の話はフィールドの転送を用意することになるしCodableからまた一歩遠ざかるなあ
Avatar
hiragram 26-Oct-17 05:43 AM
@omochimetaru jsonのキーの名前とアプリ内で使う名前が違うとかそういうのはそこで吸収するようにしてるからjsonのいけてなさにアプリがひきずられることがなくなっていいよ
Avatar
tarunon 26-Oct-17 05:43 AM
@omochimetaru @hiragram JSONから生成されるのがHoge.JSONなのでHogeをHoge.JSONから転写するのがしんどくなりそう
Avatar
Kishikawa Katsumi 26-Oct-17 05:44 AM
まあAPIから受け取る値についてはAPIが外部のものかコントローラブルなのかによっても変わるけど、外部のAPIだったらURLは規格としておかしいけどAPIレスポンスとしては正しいみたいなものも来るのでStringで受け取ってから考えるとかはよくあると思います。
Avatar
omochimetaru 26-Oct-17 05:45 AM
URLって結構クエリストリング部分のマルチバイト文字エンコーディングとか挙動ブレがあって、型付けしたらはみ出して詰むとかまあまあ怖い
05:46
たるのんがいってたパニーコードとかもそう
Avatar
Kishikawa Katsumi 26-Oct-17 05:46 AM
まあURLは例としては極端なので一般化は難しいですね。
Avatar
takasek 26-Oct-17 05:47 AM
URLだけじゃなくて、CGSizeとかでも辛みが回収されてよさそう Codableだと CGSize(width: 100, height: 50) に対応するのは { "width": 100, "height": 50 } ではなくて [100, 50] なんですよ
Avatar
omochimetaru 26-Oct-17 05:47 AM
マジw
Avatar
Kishikawa Katsumi 26-Oct-17 05:48 AM
ただまあちょっと前にMastodonのJSONが id: Int から id String に変わったとかあるので、外部APIを最初に受けるところはあまり厳格にしてもというのはあります。
Avatar
tarunon 26-Oct-17 05:48 AM
import Foundation struct Model<Base: Modelable> { var base: Base } protocol Modelable { var model: Model<Self> { get } } extension Modelable { var model: Model<Self> { return Model(base: self) } } struct Hoge: Codable, Modelable { fileprivate var int: Int fileprivate var url: String? } extension Model where Base == Hoge { var int: Int { return base.int } var url: URL? { return base.url.flatMap(URL.init) } } func x(hoge: Hoge) { hoge.model.url // URL? }
よさそう
😮 1
Avatar
Kishikawa Katsumi 26-Oct-17 05:48 AM
コントロールできるAPIで自動生成とか厳格にできると思います。
Avatar
omochimetaru 26-Oct-17 05:48 AM
MastodonのJSONが id: Int から id String に変わったとかある
oh...
Avatar
tarunon 26-Oct-17 05:48 AM
まーた丼か
05:48
あいつはほんまに
Avatar
hiragram 26-Oct-17 05:49 AM
おっマストドンまだ行きてたのか!
Avatar
takasek 26-Oct-17 05:49 AM
💭 Mastodonを一般的Webサービスのレベルと同等に語るのは…
Avatar
hiragram 26-Oct-17 05:49 AM
マストドンもっと他にやることあるよな!な!
Avatar
tarunon 26-Oct-17 05:49 AM
壊れたHTML投げつけてくるのって治ったんですか
Avatar
omochimetaru 26-Oct-17 05:49 AM
コントロールできるAPIで自動生成とか厳格にできると思います
これになりたい
Avatar
Kishikawa Katsumi 26-Oct-17 05:49 AM
別にアナウンスなしで、というわけじゃ無いので、問題ないかと。Swiftの変更とかとかわらない。
Avatar
takasek 26-Oct-17 05:50 AM
Swagger Codegen的な
Avatar
banjun 26-Oct-17 05:50 AM
マストドンid: Int のサーバとid: Stringのサーバと両方存在してつらい
Avatar
omochimetaru 26-Oct-17 05:50 AM
あーーーー
05:50
マストドンだとそういうことになるのか
Avatar
Kishikawa Katsumi 26-Oct-17 05:51 AM
まあ外部のI/Oは意図して/しないにかかわらず突然変わりうるという前提で作るのは我々の責任なので。
05:52
変わったら潔くクラッシュするというのはそれはそれでアリ。
Avatar
tarunon 26-Oct-17 05:53 AM
Tagged Extension、この間のおもちのsubscript filterの応用でsetも出来るように出来ないかしら
Avatar
omochimetaru 26-Oct-17 05:57 AM
struct Cat { subscript(ex ex: Void) -> Ex<Cat> { get { return Ex(self) } set { self = newValue.t } } var age: Int = 3 } struct Ex<T> { init(_ t: T) { self.t = t } var t: T } var cat = Cat() cat[ex: ()].t.age = 6 print(cat) // Cat(age: 6)
05:58
いろいろ雑だけど肝の仕組みは動きそう↑
Avatar
tarunon 26-Oct-17 05:58 AM
extensionで一括subscript定義はsetterがあるからムリかな?
Avatar
omochimetaru 26-Oct-17 05:58 AM
subscriptの引数が無駄になるっていうのが・・・
Avatar
tarunon 26-Oct-17 05:59 AM
そこは良い考えがある
Avatar
omochimetaru 26-Oct-17 05:59 AM
あ、あれか、オーバーロード法
Avatar
tarunon 26-Oct-17 05:59 AM
適当にありえないfunction定義して
05:59
そうそう
Avatar
omochimetaru 26-Oct-17 05:59 AM
www
Avatar
tarunon 26-Oct-17 06:00 AM
func M<A: Modelable>(_ arg: A) -> Never { fatalError() }
こいつ作っておけば cat[M].t.age = 6ってできるんじゃん?
Avatar
omochimetaru 26-Oct-17 06:03 AM
cat[Rx].tap.subscribe ...
06:03
↑だと書き戻しが無いから例が悪いか
Avatar
tarunon 26-Oct-17 06:17 AM
extensionに一括setterむりぽ
06:17
というか別に引数必要無いシーンでsubscript使う意味はなかった
Avatar
omochimetaru 26-Oct-17 06:18 AM
subscript使う意味は書き戻しでしょ?
Avatar
tarunon 26-Oct-17 06:18 AM
varで良い
06:18
subscriptの価値は引数を与えて読み書き可能なプロパティを絞れるところなので
06:22
import Foundation struct Model<Base: Modelable> { var base: Base } protocol Modelable { var model: Model<Self> { get } } extension Modelable { var model: Model<Self> { return Model(base: self) } } struct Hoge: Codable, Modelable { fileprivate var int: Int fileprivate var url: String? var model: Model<Hoge> { get { return Model(base: self) } set { self = newValue.base } } } extension Model where Base == Hoge { var int: Int { get { return base.int } set { base.int = newValue } } var url: URL? { get { return base.url.flatMap(URL.init) } set { base.url = newValue?.absoluteString } } } func x(hoge: Hoge) { hoge.model.int var hoge = hoge hoge.model.url = URL(string: "https://www.google.com") }
いけた。
06:22
Mutableにしたいときは自前で書く
06:24
MutableなExtensionでもいけました
06:24
struct Model<Base: Modelable> { var base: Base } protocol Modelable { var model: Model<Self> { get } } extension Modelable { var model: Model<Self> { get { return Model(base: self) } set { self = newValue.base } } } struct Hoge: Codable, Modelable { fileprivate var int: Int fileprivate var url: String? } extension Model where Base == Hoge { var int: Int { get { return base.int } set { base.int = newValue } } var url: URL? { get { return base.url.flatMap(URL.init) } set { base.url = newValue?.absoluteString } } } func x(hoge: Hoge) { hoge.model.int var hoge = hoge hoge.model.url = URL(string: "https://www.google.com") }
06:24
うん、よさそう
Avatar
banjun 26-Oct-17 06:39 AM
おお
Avatar
omochimetaru 26-Oct-17 06:41 AM
varで良いってそういう意味か。たしかに。
06:41
varだと書き戻しが事前定義した静的な対象しか取れなくて、subscriptだとそれが実行時の値になるわけか。
Avatar
tarunon 26-Oct-17 06:41 AM
そうそう
Avatar
omochimetaru 26-Oct-17 06:42 AM
で、funcだと書き戻しができないと。
Avatar
tarunon 26-Oct-17 06:42 AM
subscriptはジェネリックなプロパティと言える
Avatar
omochimetaru 26-Oct-17 06:42 AM
そう考えるとそれぞれちゃんと役割が別れてるなあ
Avatar
tarunon 26-Oct-17 06:48 AM
本音を言うとModelに対してJSON<Model>を作りたい (edited)
Avatar
Nezumisashi 26-Oct-17 06:55 AM
上のほうのURL?のDecode、ちょっと使えなさそうだけど、こういう方法もということで載せます。エンコード・デコードのカスタマイズも若干可能。 https://gist.github.com/rizumita/ae789fc056805f3843a946c76e1206f8
Avatar
tarunon 26-Oct-17 06:59 AM
ArrayとDictionaryを考慮しないといけないかなというのと、ネストしたらどうなるかしらというのが気になる
Avatar
Nezumisashi 26-Oct-17 07:05 AM
ArrayとかだとArrayのextensionが必要になったり、たぶん面倒です。可能かも検証してないです。なのでちょっと使えなさそうということで。
Avatar
rintaro 26-Oct-17 07:12 AM
URL を URLComponents として保持するのもありなのかも?と思ったけど、これはどういう状態なんだろうか。
import Foundation var comps = URLComponents(string: "")! comps.url! // (no URL)
(edited)
Avatar
omochimetaru 26-Oct-17 07:14 AM
URLComponentsはわからないけど、 NSDateComponentsは、抜けをゆるすタプル表現みたいなもので、そこからNSDateを構築する感じだったから
07:15
↑の例も、いろいろたりなくて、その状態だと .url が作れないって感じ?
Avatar
Kishikawa Katsumi 26-Oct-17 07:15 AM
URLComponentsは本当にユーティリティなのでそれで保持するのはやめたほうがいいと思います。
Avatar
omochimetaru 26-Oct-17 07:16 AM
URL -> URLComponents -> URL でラウンドトリップが完全に成立してるのか心配・・・
Avatar
Kishikawa Katsumi 26-Oct-17 07:17 AM
DateComponentsとかと同様にDateまたはURLを作って終わり。
Avatar
rintaro 26-Oct-17 07:17 AM
@Kishikawa Katsumi 的には UUID も String で持つべきだと思います?
Avatar
Kishikawa Katsumi 26-Oct-17 07:18 AM
APIから受ける値はStringで持ったほうがいいと思いますね。
Avatar
omochimetaru 26-Oct-17 07:19 AM
あ〜
07:19
サーバーの実装がタコだと、小文字大文字違いによって、クエリ通らないとかありえるか・・・
Avatar
Kishikawa Katsumi 26-Oct-17 07:20 AM
UUIDはそれこそ振る舞いというか性質というか(なんていうのが適切かわからないですけど)は手段であって、文字列以上のものではないと思います。
07:21
APIとかモデルを規定するのにこのUser IDはUUIDですよというのを表明する意味でモデルのプロパティを UUID にするのはもちろんやるべきですし、私もそう書きます。
Avatar
rintaro 26-Oct-17 07:28 AM
ごめんなさい、ちょっと違いがわからなかったです。 モデルの User ID プロパティを UUID で定義するなら、 UUID を String で持つべきなのはどういうケースですか? (edited)
Avatar
omochimetaru 26-Oct-17 07:28 AM
(UUIDという型は定義するけど内部表現としては文字列で持つという事かな?
Avatar
rintaro 26-Oct-17 07:29 AM
アプリでUUID生成する場合は UUID、サーバから受ける場合は String?
Avatar
Kishikawa Katsumi 26-Oct-17 07:31 AM
別にすべてStringで受け渡しするべき、というような極端な話ではないということを伝えたかったのです。難しいですね。
07:31
外部APIから受け取るものはStringの方が望ましい場合が多い、
07:32
ただ、それをアプリで使うときはStringじゃなくてUUIDを受け取るような設計の方が良いことが多いと思います。
07:32
例えば、そのモデルを更新したり、こちらから生成するときのイニシャライザはUUIDを引数に取る方がいいです。
07:33
UUID -> Stringは失敗することはあり得ないので。
07:33
外のAPIからくる値がUUID型だったらUUIDで受けていいけど、大抵はStringなので、String => UUIDは失敗することがあるし、失敗は自明ではない(ことが多い)ので水際で弾くよりはStringでいったん受け入れる方が現実的、みたいな主張です。 (edited)
Avatar
rintaro 26-Oct-17 07:34 AM
なんとなく意図はわかった気がします。ありがとうございます!
🙏🏻 1
Avatar
takasek 26-Oct-17 07:41 AM
Typed Dataへのパースと、 Domain-specific validationが一体化してるほうがいいか、分けてたほうがいいか という判断基準でしょうかね
Avatar
rintaro 26-Oct-17 07:44 AM
@takasek 元ネタURLください!
Avatar
tarunon 26-Oct-17 01:22 PM
今気が付いたけどModel<Foo>、Realmで良く見るワークアラウンドそのものだし、同じ事がRealmで出来るかも
Avatar
takasek 26-Oct-17 02:24 PM
ボイラープレート消せる方向性探りたいですね
14:26
URLをStringとして持つ話、 - そこを型として明示したい - url.flatMap {URL(string: $0)} を都度書きたくない と思ったけど、👇このアプローチどうですかね
/// デコードしたStringと、TypedなURLは纏めて独自型に押し込めるほうがいい struct RobustURL: Codable { let rawValue: String var typed: URL? { return URL(string: rawValue) } func encode(to encoder: Encoder) throws { var container = encoder.singleValueContainer() try container.encode(rawValue) } init(from decoder: Decoder) throws { rawValue = try decoder.singleValueContainer().decode(String.self) } } /// CoreGraphicに依存しない独自型 struct Size: Codable { let width: Double let height: Double } import CoreGraphics extension Size { var asCGSize: CGSize { return CGSize(width: width, height: height) } } struct Fuga: Codable { let url1: RobustURL // 不正なURLが来うることを型として示せる let url2: RobustURL // 不正なURLが来うることを型として示せる let url3: URL // 不正なURLが来ないことを型として示せる let size: Size } let data = """ { "url1": "https://failable.url", "url2": "不正なURL", "url3": "https://ensured.url", "size": { "width": 100, "height": 50 } } """.data(using: .utf8)! let fuga = try! JSONDecoder().decode(Fuga.self, from: data) fuga.url1.typed // https://failable.url fuga.url2.typed // nil fuga.url3 // https://ensured.url fuga.size.asCGSize // {w 100 h 50} let json = try! JSONEncoder().encode(fuga) print(String(data: json, encoding: .utf8)!) // {"size":{"width":100,"height":50},"url3":"https:\/\/ensured.url","url1":"https:\/\/failable.url","url2":"不正なURL"}
Avatar
tarunon 26-Oct-17 02:29 PM
ウソもデコードできるURL型を自分で定義これすね
Avatar
takasek 26-Oct-17 02:30 PM
ああー…そこで言われてましたね
Avatar
tarunon 26-Oct-17 02:34 PM
enumかRawValueで悩む
Avatar
takasek 26-Oct-17 02:40 PM
encodeで元の値に戻るのを期待するかどうかですかね
Avatar
tarunon 26-Oct-17 02:41 PM
rawValue楽すね
14:43
これ
14:43
stringとしてデコードして
14:44
extension String { var asURL: URL? { get } } が生えてるのと変わらないのではと思った
14:44
RawRepresentableってCodableで特別扱い(=その値として扱われる)ってなってますかね
👀 1
Avatar
takasek 26-Oct-17 02:45 PM
関係ないStringに asURL は欲しくないですね
Avatar
tarunon 26-Oct-17 02:51 PM
struct Bar: Codable, RawRepresentable { let rawValue: String init?(rawValue: String) { self.rawValue = rawValue } }
これはエンコードできないな。
Avatar
takasek 26-Oct-17 02:56 PM
ん?試したらそれいけますね
Avatar
tarunon 26-Oct-17 02:56 PM
oya
14:57
あw
14:57
JSONEncoderはTopLevelがオブジェクト/配列じゃないとだめだった
14:57
すません
14:58
RawRepresentableにするとかなり良さそう
Avatar
takasek 26-Oct-17 02:58 PM
struct RobustURL: Codable, RawRepresentable { let rawValue: String var typed: URL? { return URL(string: rawValue) } init?(rawValue: String) { self.rawValue = rawValue } }
すっきり
😃 2
Avatar
tarunon 26-Oct-17 02:58 PM
bbb
Avatar
banjun 27-Oct-17 12:41 AM
RawRepresentable、なにも書かなくても、 {"rawValue": ...} の階層つくらないんですね、まじか‥
Avatar
norio_nomura 27-Oct-17 01:19 AM
その例だと init?(rawValue: String) も要らないんじゃないかな。
Avatar
takasek 27-Oct-17 01:21 AM
昨日書かないとコンパイルエラー起こったと思ったんですが、今やったら削っても通りました…
Avatar
norio_nomura 27-Oct-17 01:21 AM
publicにする時には要るか。
01:21
internalなら要らないですね。
Avatar
takasek 27-Oct-17 01:22 AM
ですね
Avatar
omochimetaru 27-Oct-17 02:00 AM
プロトコルを定義する時に mutating func は mutating をつけておかないと、structで実装するときに実装できなくなっちゃうけど、 どうせいま考えてる実装がclassしかないとき、 ひとつひとつmutatingをつけるのが面倒だし意味がないので付けてなくって、 でもその状態だとどうせ struct で実装できないから、 protocol 自体に : class をつけることが多いんだけど
02:01
みんなどんな感じ
Avatar
koher 27-Oct-17 02:02 AM
なんか protocolmutating 関連の Proposal なかったっけ?
Avatar
omochimetaru 27-Oct-17 02:02 AM
マジ 記憶にない 気になる
Avatar
koher 27-Oct-17 02:02 AM
気のせいかな?
Avatar
omochimetaru 27-Oct-17 02:03 AM
weakのやつならある
Avatar
Biacco42 27-Oct-17 02:03 AM
: class にしてしまっている
Avatar
tarunon 27-Oct-17 02:05 AM
: classで思い出したけどこれ。
protocol Foo: class {} class Bar<X: class> {} Bar<Foo>() // 🙅
Avatar
omochimetaru 27-Oct-17 02:05 AM
あれ、 :class ってそこでもつかえる? :AnyObject にしてた。
Avatar
tarunon 27-Oct-17 02:05 AM
あ、AnyObjectか、でもダメだよ
Avatar
omochimetaru 27-Oct-17 02:07 AM
3行目はそれは無理ではって思う
02:07
protocolは型じゃない(?)し
Avatar
tarunon 27-Oct-17 02:07 AM
じゃあArray<Animal>もダメでは?
Avatar
omochimetaru 27-Oct-17 02:11 AM
クラス: varが作れる、引数の型にできる、型制約にできる、型パラメータにできる シンプルprotocol: varが作れる、引数の型にできる、型制約にできる、型パラメータにできない 一般protocol: varが作れない、引数の型にできない、型制約にできる、型パラメータにできない
02:13
言語仕様としてExistential周りの制約が緩まれば、それらもできるようになる可能性はある
Avatar
tarunon 27-Oct-17 02:13 AM
実は裏ワザもある
@objc protocol Foo: class {} class Bar<X: AnyObject> {} Bar<Foo>() // 🙆
Avatar
omochimetaru 27-Oct-17 02:13 AM
wwww
Avatar
Biacco42 27-Oct-17 02:14 AM
えぇ。。。
Avatar
omochimetaru 27-Oct-17 02:14 AM
@objc は深入りしたくない・・・互換性のためにいろいろ諦めてそうだしちゃんと考えて無さそう (edited)
02:14
ObjCのプロトコルをインポートしてきた時に @optional なメソッドとかSwift上にそんな概念ないのにちゃんと考慮されたりするし
02:15
しらんしらん
02:16
@Biacco42 > : class にしてしまっている :class つけなくてもその前提条件だとコンパイルはできるんだけど、 考慮せずぜんぶ func にしてるんだって自覚を表明するためにつけといたほうがマシかなって思ってる
👀 1
Avatar
koher 27-Oct-17 02:17 AM
AnyObject って参照型なら OK じゃなくてクラスじゃないとダメなのか。
1> let a: () -> Int = { 42 } 2. let b: AnyObject = a error: repl.swift:2:20: error: value of type '() -> Int' does not conform to specified type 'AnyObject' let b: AnyObject = a ^ as AnyObject
02:18
しかもプロトコルじゃないのか。 https://developer.apple.com/documentation/swift/anyobject
typealias AnyObject
Avatar
omochimetaru 27-Oct-17 02:18 AM
クロージャって値型だと思ってた
Avatar
koher 27-Oct-17 02:18 AM
クロージャは参照型です。
Avatar
tarunon 27-Oct-17 02:18 AM
Builtin.AnyObjectですよ
Avatar
omochimetaru 27-Oct-17 02:18 AM
それってどこから判断するんですか?
Avatar
koher 27-Oct-17 02:18 AM
The Swift Programming Language に書いてあった
Avatar
omochimetaru 27-Oct-17 02:18 AM
なるほど。
02:23
ちなみに↑みたいなパターンだと僕は Box<T> に入れちゃう事がある
Avatar
tarunon 27-Oct-17 02:24 AM
あれ?3からautoboxingじゃなかったっけ
02:24
as AnyObject
02:24
クロージャだけ埒外なのか
Avatar
sonson 27-Oct-17 02:24 AM
議論が難しい
Avatar
omochimetaru 27-Oct-17 02:25 AM
あーごめん 俺がBoxに入れたのは同一性判定がしたかったからだ
02:25
でも参照型ってことはクロージャのままでもできるのか?
Avatar
koher 27-Oct-17 02:26 AM
1> let a: () -> Int = { 42 } a: () -> Int = 0x00000001000c5030 $__lldb_expr8`closure #1 () -> Swift.Int in __lldb_expr_7 at repl.swift:1 2> let b = a b: () -> Int = 0x00000001000c5030 $__lldb_expr8`closure #1 () -> Swift.Int in __lldb_expr_7 at repl.swift:1 3> a === b error: repl.swift:3:3: error: cannot check reference equality of functions; operands here have types '() -> Int' and '() -> Int' a === b ~ ^ ~
Avatar
omochimetaru 27-Oct-17 02:26 AM
var f: () -> String = { "hello" } var array: [() -> String] = [] array.append(f) print(array[0] === f)
/Users/omochi/temp/swer/Sources/swer/main.swift:5:16: Cannot check reference equality of functions; operands here have types '() -> String' and '() -> String'
02:26
できない
Avatar
koher 27-Oct-17 02:27 AM
=== のオペランドの型が AnyObject なのかも。
Avatar
tarunon 27-Oct-17 02:28 AM
let c = { (i: Int) in print("\(i)") } func f(i: Int) { print("\(i)") } (c as AnyObject) === (c as AnyObject) // false (f as AnyObject) === (f as AnyObject) // false
まあそもそもBoxのポインタ比較だと思うんで
02:28
毎回Box生成してるから中身の比較はできて無さそう
Avatar
omochimetaru 27-Oct-17 02:29 AM
うーんやっぱ値型っぽいんだよなあ手触りが
02:29
あーでもあれか
Avatar
koher 27-Oct-17 02:29 AM
↓こういうところが参照型?
var a = 0 let b: () -> Int = { a = a + 1; return a } let c = b print(b()) // 1 print(c()) // 2
Avatar
omochimetaru 27-Oct-17 02:29 AM
スコープオブジェクトのカウンタが増えるのか、スコープオブジェクトのプロパティのカウンタが増えるのか、の違いがあるのか。
02:30
@koher キャプチャした変数をプロパティにもつstructとみなせるなあと考えていました
Avatar
norio_nomura 27-Oct-17 02:30 AM
@convention()によって挙動がいろいろですね。
Avatar
omochimetaru 27-Oct-17 02:30 AM
@norio_nomura 3種類ぐらいありますよね
Avatar
koher 27-Oct-17 02:30 AM
まあ実際にコピー時には関数の実体をコピーしてるわけじゃなくてポインタをコピーするだけだし参照型なのでは。
Avatar
omochimetaru 27-Oct-17 02:31 AM
Cコンベンションな8バイトポインタ、ObjC runtime互換なブロックオブジェクト8バイト、SwiftのFat Pointer 8x2バイト
Avatar
koher 27-Oct-17 02:31 AM
キャプチャした変数をプロパティにもつstruct
それなら↑のコードの c()1 にならないとおかしい。
Avatar
omochimetaru 27-Oct-17 02:32 AM
あー、a自体は値型だからか。
Avatar
norio_nomura 27-Oct-17 02:33 AM
@conventionは7種類あるらしい
Avatar
omochimetaru 27-Oct-17 02:33 AM
たしかに。値型をキャプチャして書き換えた時の挙動はスコープオブジェクトに対する参照型なのか
Avatar
norio_nomura 27-Oct-17 02:33 AM
swift - The Swift Programming Language
02:34
- ``@convention(thin)`` indicates a "thin" function reference, which uses the Swift calling convention with no special "self" or "context" parameters. - ``@convention(thick)`` indicates a "thick" function reference, which uses the Swift calling convention and carries a reference-counted context object used to represent captures or other state required by the function. - ``@convention(block)`` indicates an Objective-C compatible block reference. The function value is represented as a reference to the block object, which is an ``id``-compatible Objective-C object that embeds its invocation function within the object. The invocation function uses the C calling convention. - ``@convention(c)`` indicates a C function reference. The function value carries no context and uses the C calling convention. - ``@convention(objc_method)`` indicates an Objective-C method implementation. The function uses the C calling convention, with the SIL-level ``self`` parameter (by SIL convention mapped to the final formal parameter) mapped to the ``self`` and ``_cmd`` arguments of the implementation. - ``@convention(method)`` indicates a Swift instance method implementation. The function uses the Swift calling convention, using the special ``self`` parameter. - ``@convention(witness_method)`` indicates a Swift protocol method implementation. The function's polymorphic convention is emitted in such a way as to guarantee that it is polymorphic across all possible implementors of the protocol.
Avatar
omochimetaru 27-Oct-17 02:34 AM
多いw
02:35
@convention(thin) indicates a "thin" function reference, which uses the Swift calling convention with no special "self" or "context" parameters. あー、ここに出てくる、 self と context がミソっぽいなあ 今の話
Avatar
tarunon 27-Oct-17 02:35 AM
これだとどうなるんだろ
let b: () -> Int = { [x=a] in a = x + 1; return a }
Avatar
norio_nomura 27-Oct-17 02:35 AM
一応確認したけど、どれもAnyObjectには入らなかった>7種類。
Avatar
koher 27-Oct-17 02:36 AM
話戻るけど
プロトコルを定義する時に mutating func は mutating をつけておかないと、structで実装するときに実装できなくなっちゃうけど、 どうせいま考えてる実装がclassしかないとき、
class やめるのダメ?
Avatar
omochimetaru 27-Oct-17 02:36 AM
var a = 3 let b: () -> Int = { [x=a] in a = x + 1 return a } print(b()) // 4 print(b()) // 4 print(b()) // 4
02:37
ああ、c忘れてた
Avatar
norio_nomura 27-Oct-17 02:37 AM
Objective-Cでidにはブロックが入った気がするから、AnyObject != id
Avatar
omochimetaru 27-Oct-17 02:37 AM
var a = 3 let b: () -> Int = { [x=a] in a = x + 1 return a } let c = b print(b()) print(c()) print(b()) print(c())
4 4 4 4
Avatar
tarunon 27-Oct-17 02:37 AM
あーまぁそうなるか、そうだね
Avatar
omochimetaru 27-Oct-17 02:39 AM
@koher > class やめるのダメ? classやめた瞬間に代入文の意味が変わってくるし 共有ができなくなるからいろいろ状況が変わる
Avatar
koher 27-Oct-17 02:41 AM
共有は↓だけ class 使うとか?
class Ref<Value> { var value: Value }
Avatar
omochimetaru 27-Oct-17 02:42 AM
その時の例でいうとツリーノードを作ってて親への弱参照も欲しかったし、継承機能も使ってた。
02:43
何もかも Ref で包めば参照グラフは作れるけど 何もかも包むとC++みたいで大変だし、そのパターンだと継承ができない
02:43
クラス制約付きのprotocol と親クラスの比較だと、 親クラスだと1つしか持てないから特性の合成が表現できないし protocol なら実装漏れチェックができるけど親クラスだとできない
02:44
クラス特有の機能が使いたくて、かつ、親クラスじゃなくて protocol を使いたい状況ってのはあると思ってて
02:44
値型に無理によせても、それらの機能を手動でエミュレートしていく事になるから、それなら最初からclassに寄せたほうが良いと思う
02:46
逆に TypeErasure でどこまでができて、どこまでならクラスにのっかったほうがいいのか っていうプラクティスは最近考え中。
Avatar
koher 27-Oct-17 02:47 AM
うーん、 C の &* がほしくなってきた。 struct&* の世界、実は良かったのでは? mallocfree が面倒だっただけで、そこをリファレンスカウントで勝手にやってくれるなら。
Avatar
omochimetaru 27-Oct-17 02:49 AM
スタックアロケートなオブジェクトはリファレンスカウンティングできませんよ。
Avatar
koher 27-Oct-17 02:49 AM
継承は半ばアンチパターン化してると思うからそれはやめて、抽象化はサブタイピングじゃなくてジェネリクスでやれば、問題になるのって共有したいときくらいで、簡単に参照型化できてメモリ管理をいい感じにやってくれたらそれが良いのかも? & じゃなくて、実体コピーした上で参照型化かな。
02:49
参照型化した瞬間にヒープに領域確保されてコピーされる。
Avatar
omochimetaru 27-Oct-17 02:50 AM
それだと既存の参照がdanglingになります
Avatar
koher 27-Oct-17 02:50 AM
既存の参照?
Avatar
omochimetaru 27-Oct-17 02:50 AM
たとえば・・・
Avatar
koher 27-Oct-17 02:51 AM
重要なのは参照がとれることじゃなくて、任意の値型を共有したいときにヒープに確保して(もちろんリファレンスカウント付き)共有できることかと。
Avatar
omochimetaru 27-Oct-17 02:51 AM
あー、エスケープする前にコピーされてるから、それはできる気がしてきた。
Avatar
koher 27-Oct-17 02:51 AM
struct Foo を作ったけど、それを共有したいときは Foo * として取り扱えるとうれしい。 (edited)
02:52
* の意味は C と同じになるけど、 & はちょっと違うから別の記号が良さそう。
Avatar
omochimetaru 27-Oct-17 02:53 AM
なんか変な破綻が起きる気がしなくもないけど (edited)
02:53
必要な場所では Box<Stone> になっているボクシングが
02:53
全部自動で行われているような状態になるのかな
Avatar
koher 27-Oct-17 02:54 AM
うん、やってることは Box<Foo> と同じなんだけど
02:54
簡易的な構文があるとうれしいねって話。
Avatar
omochimetaru 27-Oct-17 02:54 AM
Go言語のスタック退避GCを
02:54
同じ話を逆方向から見た話か
02:54
ちなみにrustには
02:54
box 1
02:54
って、boxって書くとboxingされますよ。
Avatar
koher 27-Oct-17 02:54 AM
OptionalArray みたいに BoxReference でもいい)のシュガーがあればいいのかも。
02:55
Foo*Reference<Foo>
Avatar
tarunon 27-Oct-17 02:55 AM
weak var foo: Foo*? こうなる? (edited)
Avatar
koher 27-Oct-17 02:56 AM
class Reference<Value> { var value: Value }
02:56
prefix func * もほしいか
Avatar
omochimetaru 27-Oct-17 02:56 AM
それ自体は作れそうですね。
Avatar
koher 27-Oct-17 02:57 AM
で、 Foo*Reference<Foo> だとうれしくない?
Avatar
omochimetaru 27-Oct-17 02:57 AM
ああ、tarunonが言ってるのは、boxの型の略記か。
Avatar
tarunon 27-Oct-17 02:57 AM
これweak参照どうやるんですか
Avatar
omochimetaru 27-Oct-17 02:57 AM
weak var a: Reference<Int>? で良いんじゃない? (edited)
Avatar
koher 27-Oct-17 02:58 AM
weak var foo: Foo*? かな?
Avatar
tarunon 27-Oct-17 02:58 AM
structがweakになれないだけで weak varは作れるんだっけか
02:58
いつもぐちゃぐちゃになる
Avatar
omochimetaru 27-Oct-17 02:58 AM
いや、Referenceはそもそもclassだから
02:58
普通のswiftの話だよ
02:58
あ、違うのか?
Avatar
rintaro 27-Oct-17 02:58 AM
ちょっと戻るけど
let a: () -> Int = { 42 } let block = a as @convention(block) () -> Int as AnyObject
👍 1
Avatar
omochimetaru 27-Oct-17 02:58 AM
いや、そうだ。class Box じゃないとそもそもヒープ退避できない。
03:00
@rintaro
let a: () -> Int = { 42 } let block = a as AnyObject print(block)
as AnyObject はそもそもそのままできそうですよ
Avatar
rintaro 27-Oct-17 03:00 AM
あら。
Avatar
omochimetaru 27-Oct-17 03:00 AM
あ、ちがうか、 === の話ですか?
Avatar
tarunon 27-Oct-17 03:00 AM
NSMallocBlockとかになるの?
Avatar
rintaro 27-Oct-17 03:01 AM
僕が議論が追えてないだけだと思う。
Avatar
omochimetaru 27-Oct-17 03:01 AM
let a: () -> Int = { 42 } print(a as AnyObject === a as AnyObject) // false let b = a as @convention(block) () -> Int print(b as AnyObject === b as AnyObject) // true
03:01
いや、完璧に追えてますね、なるほど!
Avatar
tarunon 27-Oct-17 03:02 AM
ほーー
Avatar
omochimetaru 27-Oct-17 03:02 AM
これはおもしろいw
03:03
() -> Int false @convention(block) () -> Int true
Avatar
koher 27-Oct-17 03:03 AM
↑は aas AnyObject でボクシングされるけど
03:03
b はすでに AnyObject だから
Avatar
omochimetaru 27-Oct-17 03:03 AM
type(of: a) と type(of: b) をprintしてみた↑
Avatar
koher 27-Oct-17 03:03 AM
何も変化してないってことやんね?
03:04
当然↓にはなる。
let a: () -> Int = { 42 } let b = a as AnyObject b === b // true
Avatar
omochimetaru 27-Oct-17 03:04 AM
let a: () -> Int = { 42 } print(type(of: a)) print(a as AnyObject === a as AnyObject) let b: @convention(block) () -> Int = a as @convention(block) () -> Int print(type(of: b)) print(b as AnyObject === b as AnyObject) var x: AnyObject = b // NG: value of type '@convention(block) () -> Int' does not conform to specified type 'AnyObject'
03:04
bはあくまでコンベンションブロックなクロージャであってAnyObjectではないみたい。
03:05
まあ実際にはAnyObject互換なオブジェクトなんだろうけど・・
Avatar
norio_nomura 27-Oct-17 03:05 AM
protocol P { func method() } type(of: P.method)
でコンパイラがクラッシュする
😫 1
Avatar
omochimetaru 27-Oct-17 03:05 AM
クロージャのようなAnyObjectのようなやつ
Avatar
tarunon 27-Oct-17 03:05 AM
is NSObject?
Avatar
omochimetaru 27-Oct-17 03:05 AM
@norio_nomura www
03:06
報告価値ありそうだけど今まで誰も踏んで無さそう・・・
Avatar
norio_nomura 27-Oct-17 03:06 AM
dump(P.method)もダメだった。
Avatar
omochimetaru 27-Oct-17 03:07 AM
dumpってなんですか?
Avatar
koher 27-Oct-17 03:07 AM
↓これ納得行かないな・・・
var x: AnyObject = b // NG: value of type '@convention(block) () -> Int' does not conform to specified type 'AnyObject'
(edited)
Avatar
omochimetaru 27-Oct-17 03:07 AM
あった。
Avatar
norio_nomura 27-Oct-17 03:07 AM
コード内でlldbのpoをやるみたいなの。>dump (edited)
Avatar
omochimetaru 27-Oct-17 03:07 AM
@koher もうほんと形式的な話でしょうねw
Avatar
koher 27-Oct-17 03:08 AM
闇を感じる 2 行だ・・・。
print(b as AnyObject === b as AnyObject) // true var x: AnyObject = b // NG: value of type '@convention(block) () -> Int' does not conform to specified type 'AnyObject'
Avatar
rintaro 27-Oct-17 03:13 AM
コレみたいなものだと思えば
import Foundation let a = "str"; let b: NSString = a
Avatar
koher 27-Oct-17 03:13 AM
class Cat {} let a: AnyObject = Cat() print(type(of: a)) // Cat
func f() -> Int { return 42 } let a: AnyObject = f as AnyObject print(type(of: a)) // _SwiftValue
03:14
_SwiftValue なる型になってた。
Avatar
omochimetaru 27-Oct-17 03:15 AM
_SwiftValue、言語側のboxingでよくみる
Avatar
koher 27-Oct-17 03:16 AM
@rintaro ↓ですw
swift-string.swift:3:19: error: cannot convert value of type 'String' to specified type 'NSString' let b: NSString = a ^ as NSString
03:17
そして @rintaro さんがコンパイラのソース( C++ )に触れすぎて ; が付いてる😅
😄 1
😱 1
Avatar
rintaro 27-Oct-17 03:17 AM
そう、 as NSString なら通る。明示的なキャストを言語的に強制してるということです。
Avatar
tarunon 27-Oct-17 03:17 AM
T -> T?とか[Cat] -> [Animal] も明示するようにしよう!!!
Avatar
omochimetaru 27-Oct-17 03:18 AM
:tarunon: 絵文字ほしくなってきたな
Avatar
tarunon 27-Oct-17 03:18 AM
ww
Avatar
koher 27-Oct-17 03:18 AM
@rintaro うーん、↓はいいと思うんです。 false だから。
import Foundation let a = "str" a as NSString === a as NSString // false
03:19
納得がいかないのはさっきの ===true になるところ
Avatar
rintaro 27-Oct-17 03:21 AM
それも
import Foundation let str = "str" let b = str as NSString (b as AnyObject === b as AnyObject) // true
と同じじゃないかと。
(edited)
Avatar
koher 27-Oct-17 03:22 AM
let b: @convention(block) () -> Int = { 42 } b as AnyObject === b as AnyObject // true
03:24
でも
03:24
import Foundation let str = "str" let b = str as NSString let c: AnyObject = b // OK
03:24
ですよね?
03:24
納得がいかないのは
let b: @convention(block) () -> Int = { 42 } b as AnyObject === b as AnyObject // true let c: AnyObject = b // ERROR
👍 1
Avatar
rintaro 27-Oct-17 03:24 AM
なるほどー、そこか。
Avatar
koher 27-Oct-17 03:25 AM
純粋にバグな気がしてきました・・・
let b: @convention(block) () -> Int = { 42 } b as AnyObject === b as AnyObject // true b is AnyObject // true let c: AnyObject = b // ERROR
03:26
is AnyObjecttrue なのに代入できない・・・
Avatar
omochimetaru 27-Oct-17 03:27 AM
import Foundation let a = "aaa" a is NSString let b: NSString = a
is trueだけど代入できないのはよくあるから
03:27
それとあわせて as AnyObject === がtrueになるのが特殊?
03:28
なんだろう、一つ一つは他にも例がある現象だけど、全部の組み合わさった時が独自のふるまいになっている感じ。
Avatar
koher 27-Oct-17 03:28 AM
このあたりの特殊型変換は闇が深そう・・・この前話してた Optional も含め
Avatar
rintaro 27-Oct-17 03:28 AM
@convention(block) の時点で ObjC の世界に入っているわけだから、 AnyObject にそのまま突っ込めてもいい気はしますね。
Avatar
koher 27-Oct-17 03:28 AM
そうですよねぇ。
Avatar
omochimetaru 27-Oct-17 03:29 AM
なるほど。
Avatar
omochimetaru 27-Oct-17 04:01 AM
protocol Proto : AnyObject {} class Box1<X> {} Box1<Proto>() // OK class Box2<X: AnyObject> {} Box2<Proto>() // NG: 'Proto' is not convertible to 'AnyObject'
04:01
なんだこりゃ
Avatar
tarunon 27-Oct-17 04:10 AM
そうだよ
04:11
Array<Animal>が成り立つのはElementがconditionalじゃないから
Avatar
omochimetaru 27-Oct-17 04:11 AM
'Proto' is not convertible to 'AnyObject' ってエラーメッセージ出てるけど Proto : AnyObject なんだけどなあ
Avatar
tarunon 27-Oct-17 04:11 AM
@objc つけよう^^
Avatar
omochimetaru 27-Oct-17 04:11 AM
@tarunon のそこでいうAnimalはprotocolなのかclassなのか?
Avatar
tarunon 27-Oct-17 04:12 AM
protocolやで
Avatar
omochimetaru 27-Oct-17 04:12 AM
マジか さっきの勘違いしてた
04:12
Animalはスーパークラス世界代表
Avatar
tarunon 27-Oct-17 04:12 AM
これ今まさにRxSwiftでやらかしてしまって、対応中なのです
Avatar
rintaro 27-Oct-17 04:12 AM
protocol は protocol に準拠できない。
Avatar
omochimetaru 27-Oct-17 04:13 AM
protocol は protocol に準拠できない。
おお。ルールとしてはこれだけか。
Avatar
rintaro 27-Oct-17 04:14 AM
protocol Proto {} struct S: Proto {} func foo<P: Proto>(x: P) {} let p: Proto = S() foo(x: p) // error: cannot invoke 'foo' with an argument list of type '(x: Proto)'
これと同じですね。
Avatar
tarunon 27-Oct-17 04:21 AM
これ2桁番台でバグ報告されてるんですよね
Avatar
omochimetaru 27-Oct-17 04:26 AM
なるほど。納得。
04:27
これがあるから シンプルなプロトコルでexistential変数が作れる機能が実質役に立たないと思ってる最近。
Avatar
koher 27-Oct-17 04:29 AM
シンプルなプロトコルでexistential変数が作れる機能
禁止でいいと思ってる。
Avatar
omochimetaru 27-Oct-17 04:29 AM
ドヒャア
04:29
え、じゃあこれも反対ですか?
04:30
Generalized Existentialの、ジェネリックパラメータが無い状態だけ中途半端に実装済み、という状態と理解していて
Avatar
koher 27-Oct-17 04:30 AM
Generalized Existential もほとんどいらないと思うんよね。
Avatar
omochimetaru 27-Oct-17 04:30 AM
禁止じゃなくて発展の方向だと思ってた。
04:30
マジか
Avatar
tarunon 27-Oct-17 04:30 AM
Avatar
omochimetaru 27-Oct-17 04:30 AM
手書きType erasureは移行期間中のワークアラウンドで
04:31
Generalized Existentialがサポートされたら不要になる、という方向なのかと・・・
Avatar
koher 27-Oct-17 04:31 AM
いや、そりゃそうなんけど
04:31
実際 AnySequence とか使いたくなるケースの 8 割くらいは実はいらないんじゃないかなぁ。
Avatar
omochimetaru 27-Oct-17 04:31 AM
あと、手書きErasureとGeExの違いとして、 as とか is の挙動が
Avatar
koher 27-Oct-17 04:31 AM
Java 的な感覚が抜けてないパターンが多そう。
Avatar
omochimetaru 27-Oct-17 04:31 AM
メソッドでエミュレートしないといけないのがしんどいから言語サポートされてほしい
04:32
あるプロトコルを満たすオブジェクトをコレクションに集めるってパターンがよくあるんじゃないですかね。
Avatar
koher 27-Oct-17 04:32 AM
まあ、今の状態が中途半端なのは間違いないから、 Generilized Existential サポートするか、シンプルプロトコル型も禁止するかどっちかにしてほしい
Avatar
omochimetaru 27-Oct-17 04:32 AM
で、集めたやつらに対して、そのプロトコルのメソッドを呼び出し。
04:33
そうですね。
Avatar
koher 27-Oct-17 04:33 AM
あるプロトコルを満たすオブジェクトをコレクションに集める
うーん、これってサブタイピングをベースに抽象化しようとするからじゃないかな?
04:34
最初からプロトコル型が使えなければそもそもそういう事態にならなくない?
Avatar
omochimetaru 27-Oct-17 04:34 AM
いえ、シンプルじゃないプロトコルはそもそもExitstentialが無いので
04:34
TypeErasureを作ってからコレクションに集める話なので
04:35
最初から使えないという前提ですね
04:35
たとえば3Dシーングラフでも、プログラミング言語のASTでもいいですけど
04:35
ノードツリーに対して
Avatar
koher 27-Oct-17 04:35 AM
heterogeneous なコレクションはあるか
Avatar
omochimetaru 27-Oct-17 04:36 AM
ノードツリーをウォークして、ある特徴をみたすノードを洗い出して
04:36
一括で処理をかける
04:36
みたいな事はあると思う
Avatar
koher 27-Oct-17 04:36 AM
enum Node とか?
Avatar
omochimetaru 27-Oct-17 04:36 AM
たとえば、ASTなら、visibilityがコントロールできるノードについて全部publicにする、
04:36
というのを最近実際にやった。
04:37
enumにしてしまうとparent参照が作れないです
04:37
あ、enumならindirectでいけるのかな
Avatar
koher 27-Oct-17 04:37 AM
indirect
Avatar
omochimetaru 27-Oct-17 04:37 AM
まあでも話それてませんかね
04:38
あるメソッドを持つノード、だから、enumだと余計に面倒になる気が。
04:38
全部同じ型だし。
Avatar
koher 27-Oct-17 04:40 AM
うーん、最近サブタイピングに懐疑的で、 9 割くらいはサブタイピングなしでいけると思うんよね。さっきの参照型の話と同じで。
Avatar
omochimetaru 27-Oct-17 04:40 AM
それはわかるんですけど残り1割のための言語機能はあったほうがいいと思います
04:41
なるべく回避したいし、9割回避できるのは同意だけど、1割が書きやすいにこしたことはない。
Avatar
koher 27-Oct-17 04:41 AM
一つだけ type erasure 作ってなんとかならないかな?さっきの Reference と同じように。後は使いやすいシュガーがあれば。
Avatar
omochimetaru 27-Oct-17 04:42 AM
一つだけ?というのは、何に対して?
04:42
いまはprotocol1種類についてerasureを1つ実装しないといけない
Avatar
koher 27-Oct-17 04:42 AM
そうだな・・・
04:43
結局 Generalized Existenstial になってしまうか?
04:44
うーん、なんというか、 existential に変換する場合のオペレーションが明示的ならいいと思うんよね。
04:47
クラスも継承もサブタイピングもなくて、本当に必要な場合だけ参照や Existential に変換できる世界だと型システムがもっとシンプルになる気がしてる。今の Swift の protocol と参照型の相性が良くないような。
04:47
もちろん今の状況から現実的じゃないのはわかってるけど。
Avatar
ukitaka 27-Oct-17 05:53 AM
「protocol は protocol に準拠できない」ルールの話、いっそ { ∃X, X: Animal } という存在型を略して Animal 型と書くのをやめてぱっと見で存在型だってわかるようにすればもうちょい理解しやすくなりそうですね
Avatar
omochimetaru 27-Oct-17 05:55 AM
そのルールが間違っているように思います
05:55
実際、手書きで type erasure を書いたときはそうだし、組み込みのAnySequence は Sequenceだし。
05:56
typealias AnySequence<Element> = Any<Sequence where .Iterator.Element == Element> let strings: AnySequence<String> = ["a", "b", "c"]
05:57
manifestoのgeneralized existentialのところに、↑の例もありますが、これが実装された時互換性の観点からもAnySequene : Sequence になるはず
Avatar
tarunon 27-Oct-17 06:04 AM
06:04
これ報告したのについたコメント見る限り、コアチームとしては「protocolはprotocolに準拠できない」が正だという認識を持ってそう (edited)
06:06
↑のGeneralized existentialに習うと、
06:06
シンプルだろうが一般だろうがprotocolの存在型を示すときに
Avatar
omochimetaru 27-Oct-17 06:06 AM
ん、それは、今はそのルールがあるから、現状のこのレポートは正しい挙動になるはずって話で
06:06
僕が言っているのはそのルールは今後見直すことになるはずってこと。
Avatar
tarunon 27-Oct-17 06:07 AM
シンプルなら、Any<Animal> 一般なら、Any<Sequence where ...>と
06:07
そう表現したものを存在型ということにすれば
06:07
Animal.selfがprotocol型で準拠するものではなく、Any<Animal>.selfが具体的に準拠したりできるようになるはず
06:07
かしら?
06:08
つまり、Animal型の変数を持つときに let animal: Animalは駄目になって、
06:08
let animal: Any<Animal> がOKになると色々整合性取れてきそう
💯 1
Avatar
omochimetaru 27-Oct-17 06:08 AM
あーなるほど
06:09
Any<>で作ったExistential Type と、 protocol type は別のものだよねって認識なら
06:09
protocolはprotocolに準拠できないままで特に困らないのか。
Avatar
tarunon 27-Oct-17 06:09 AM
そうそう
06:09
それで困らないためには、シンプルプロトコルを変数の型にできる今の状態は相容れないので、
Avatar
omochimetaru 27-Oct-17 06:09 AM
Existentialの方が準拠するわけか。ああ、そっちのほうが正しいな。
Avatar
tarunon 27-Oct-17 06:11 AM
今はprotocolが、protocolとしての機能と、部分的にExistentialの機能も内包して混乱の元になってる
Avatar
omochimetaru 27-Oct-17 06:12 AM
はげしくどうい
Avatar
tarunon 27-Oct-17 06:12 AM
混乱の元というか、まあ壊れてるんですよ
06:12
かなしい
Avatar
omochimetaru 27-Oct-17 06:12 AM
なんだったんだろうね?シンプルプロトコルのExistential
06:13
ObjCのprotocolの相互運用のためにあるのかな
Avatar
tarunon 27-Oct-17 06:13 AM
ObjCのprotocol闇が深い
Avatar
rintaro 27-Oct-17 06:13 AM
P1 & P2Any<T where T: P1, T: P2> とか?
Avatar
tarunon 27-Oct-17 06:14 AM
よさそう
06:14
Any<P1 & P2> と短く表現できるならそれも有り得るかな、これは昔あったけど死んじゃったんでしたっけ (edited)
Avatar
omochimetaru 27-Oct-17 06:14 AM
Any<P1 & P2> が Exitentialになるという仕様になってほしい P1 & P2 はあくまで protocol (edited)
Avatar
rintaro 27-Oct-17 06:15 AM
protocol<P1, P2>P1 & P2 になりました。
Avatar
tarunon 27-Oct-17 06:16 AM
import UIKit class MyScrollViewDelegate: NSObject, UIScrollViewDelegate { } let myScrollViewDelegate = MyScrollViewDelegate() let tableView = UITableView() let scrollView = tableView as UIScrollView scrollView.delegate = myScrollViewDelegate tableView.delegate is UITableViewDelegate // true myScrollViewDelegate === tableView.delegate // true myScrollViewDelegate is UITableViewDelegate // false
Objc絡むととたんにやばくなるやつ
😇 1
Avatar
omochimetaru 27-Oct-17 06:18 AM
ってかそれクラッシュしそう
Avatar
tarunon 27-Oct-17 06:18 AM
しないんだなこれが
Avatar
omochimetaru 27-Oct-17 06:18 AM
・・・
Avatar
rintaro 27-Oct-17 06:18 AM
respondsToSelector で false 返すから?
Avatar
omochimetaru 27-Oct-17 06:19 AM
UITableViewDelegateって@required なメソッドもなかったっけ。
Avatar
tarunon 27-Oct-17 06:19 AM
UITableViewDelegateは全部optional funcなので
Avatar
omochimetaru 27-Oct-17 06:19 AM
ないのか。
Avatar
tarunon 27-Oct-17 06:19 AM
requiredはDataSource
Avatar
omochimetaru 27-Oct-17 06:19 AM
あ〜〜〜〜〜w
06:19
やられたw
Avatar
tarunon 27-Oct-17 06:19 AM
でも多分、required funcのあるパターンも書ける、何が起こるかは試したことがない
Avatar
omochimetaru 27-Oct-17 06:20 AM
メソッド無くてクラッシュじゃないかしら。objcではよくあること
Avatar
tarunon 27-Oct-17 06:20 AM
よくあることやな
😂 1
Avatar
rintaro 27-Oct-17 06:20 AM
それが(なるべく)無いように注意深く API 設計してるのか。。。
Avatar
tarunon 27-Oct-17 06:32 AM
unrecognized selector sent to instance 0xXXXXX いつものだw
Avatar
omochimetaru 27-Oct-17 06:37 AM
なつかしい
Avatar
koher 27-Oct-17 06:54 AM
見てない間に進んでた。
つまり、Animal型の変数を持つときに let animal: Animalは駄目になって、
let animal: Any<Animal> がOKになると色々整合性取れてきそう 良さそう。
Avatar
ukitaka 27-Oct-17 07:06 AM
よさそうですね! んで、 Animalbark() メソッドをもってるとして、Any<Animal> 型のanimal に対して animal.bark() を呼びだせるのはAny<Animal>: Animal なわけではなく、 Opening existentials のシンタックスシュガーだって考えればよさそう?
let animal: Any<Animal> = Dog() // OK animal.bark() // ↑は以下のシンタックスシュガー // aの型はA。AはAnimalに準拠。 let a = animal openas A a.bark()
Avatar
koher 27-Oct-17 07:31 AM
よさそうですね! < Any<Animal>: Animal なわけではなく (edited)
Avatar
omochimetaru 01-Nov-17 12:20 PM
struct S { var a: Int = 3, b: Int = 4 }
12:20
こんなんかけたんか
Avatar
koher 06-Nov-17 05:31 AM
CGFloat って Swift 3.1 まで FloatDoubletypealias じゃなかったっけ? https://developer.apple.com/documentation/coregraphics/cgfloat
05:31
struct になった?
Avatar
tarunon 06-Nov-17 05:31 AM
元からそうだった気がします
05:31
typealiasなのはTimeIntervalですね
Avatar
hiragram 06-Nov-17 05:31 AM
わざわざ変換して計算してた記憶なのでtypealiasじゃなかったような (edited)
Avatar
koher 06-Nov-17 05:32 AM
あれ?元から struct でしたっけ?
05:32
記憶違いのようですね。ありがとうございます。
05:33
仕様としては確実に struct の方が良いと思います。(環境によって FloatDouble に切り替わるとやっかいなので)
Avatar
omochimetaru 06-Nov-17 05:37 AM
ObjectiveC では typedef だった
Avatar
koher 06-Nov-17 06:02 AM
ObjC はそうだね。それと記憶が混ざっちゃったのかな・・・。
Avatar
omochimetaru 06-Nov-17 06:03 AM
Swiftになって CGFloat はいつも明示的変換で、おっ、ええやんけ、って思ってた気がする
Avatar
lovee 06-Nov-17 08:30 AM
あれ?自分も CGFloat は昔 DoubleFloattypealias だったような気が…Obj-Cとの記憶が混乱したのか 😇
Avatar
tarunon 06-Nov-17 08:30 AM
TimeIntervalはDoubleのエイリアスなのでそれも相まって記憶が混濁してそう
Avatar
koher 06-Nov-17 08:34 AM
TimeInterval と ObjC の両方と混同してたような気がします😅 (edited)
08:36
すくなくとも Beta時代は typealiasだったっぽい
Avatar
omochimetaru 06-Nov-17 08:38 AM
本当だ
08:38
Swift 考古学
Avatar
koher 06-Nov-17 08:38 AM
おお、なんか 32bit か 64bit かで CGFloat のコンパイルが通らなくなる夢を見てた気がしてたんですが、この頃の記憶かも。
Avatar
lovee 06-Nov-17 08:38 AM
よかったよかった記憶が正しかった
Avatar
koher 06-Nov-17 08:39 AM
swift のコミットを遡れば時期も明らかになるかと思ったけど CoreGraphics だった・・・ (edited)
Avatar
omochimetaru 06-Nov-17 08:39 AM
swift本体側のSDK overlay header?かも。
Avatar
lovee 06-Nov-17 08:39 AM
まあ確かに CoreGraphics だし import Foundation しないと使えないし
Avatar
omochimetaru 06-Nov-17 08:40 AM
swift - The Swift Programming Language
08:40
こういうのはswift側に入ってるんですよね、よくわからんけど。
08:41
CGFloat.swift.gyb あった。
08:41
@_fixed_layout public struct CGFloat { #if arch(i386) || arch(arm) /// The native type used to store the CGFloat, which is Float on /// 32-bit architectures and Double on 64-bit architectures. public typealias NativeType = Float #elseif arch(x86_64) || arch(arm64) /// The native type used to store the CGFloat, which is Float on /// 32-bit architectures and Double on 64-bit architectures. public typealias NativeType = Double #endif ... /// The native value. public var native: NativeType }
(edited)
Avatar
lovee 06-Nov-17 08:41 AM
NativeTypetypealias になったね
08:44
このファイルではこれより昔はなさそう。
Avatar
omochimetaru 06-Nov-17 08:44 AM
拡張子が変わってるけど、
Avatar
rintaro 06-Nov-17 08:44 AM
CGFloat is 32-bit on 32-bit architectures and 64-bit on 64-bit architectures for historical reasons. Rather than having it alias either Float (32-bit) or Double (64-bit), introduce a distinct struc...
Avatar
omochimetaru 06-Nov-17 08:45 AM
+public struct CGFloat { +#if arch(i386) || arch(arm) + public typealias UnderlyingType = Float +#elseif arch(x86_64) || arch(arm64) + public typealias UnderlyingType = Double +#endif
(edited)
Avatar
koher 06-Nov-17 08:45 AM
@rintaro おおお!
Avatar
omochimetaru 06-Nov-17 08:46 AM
@DougGregor DougGregor committed on 9 Jul 2014
08:46
オープンソースになる前・・・?
Avatar
koher 06-Nov-17 08:46 AM
1.0 の頃じゃない?
Avatar
hiragram 06-Nov-17 08:46 AM
1.0のリリースのときっぽ
Avatar
omochimetaru 06-Nov-17 08:46 AM
なるほど
Avatar
lovee 06-Nov-17 08:49 AM
betaからやってきてもリリースノートちゃんと読まないとこうなるんですね 😇
Avatar
omochimetaru 06-Nov-17 08:59 AM
古い仕様の事は忘れたい
Avatar
tarunon 07-Nov-17 05:32 AM
昨日話していてそんな気がしたんですが やっぱりOptionalの暗黙変換とOptionalの共変性は矛盾した結果を生むので両方入ってるのは厳しいですね
😂 1
Avatar
koher 07-Nov-17 05:52 AM
暗黙の型変換をサブタイピングっぽく振る舞わせてるのが諸悪の根源ですね・・・。
05:52
暗黙の型変換出ない本物のサブタイピングである Kotlin なら何の問題もありませんね。
// Kotlin open class Animal class Cat: Animal() // Rule A // Cat is subtype of Animal run { val cat: Cat = Cat() val animal: Animal = cat } // Rule B // Int is subtype of Int? run { val int: Int = 0 val intOptional: Int? = int // 0 } // Rule C // Optional has covariance run { val catOptional: Cat? = null val animalOptional: Animal? = catOptional // null } // Question // What happen replace `Cat : Animal` to `Int : Int?` run { val intOptional: Int? = null val intOptionalOptional: Int?? = intOptional // null (Int?? == Int?) }
Avatar
tarunon 07-Nov-17 05:53 AM
String?.none as? Int? => Int??.some(.none) は確かにおかしい結果を生むんですが、それ以前に共変性周りが崩壊していることに気がついた
Avatar
koher 07-Nov-17 05:53 AM
ただし Int?? でネストを表現できないですが😅
Avatar
tarunon 07-Nov-17 05:53 AM
Kotlinはネストしないからいけます
Avatar
koher 07-Nov-17 05:54 AM
Swift では本来 IntInt? のサブタイプじゃないですからねぇ。
Avatar
tarunon 07-Nov-17 05:54 AM
サブタイプじゃないのにサブタイプっぽく振る舞わせてるのがダメ
Avatar
koher 07-Nov-17 05:55 AM
はい。そこがヤバイです。
Avatar
tarunon 07-Nov-17 05:55 AM
あとは共変性もウソなのではという気がしないでもないけどまあそれは
05:55
えゔぉりゅーしょん書かなきゃいけないンゴねぇ…
Avatar
koher 07-Nov-17 05:56 AM
共変性はまあいいんじゃないですか? Optional<Cat>Optional<Animal> のサブタイプでも、 IntInt? のサブタイプでなければ Optional<Int>Optional<Int?> のサブタイプにならないですし。
05:56
暗黙の型変換はともかく、サブタイプのように振る舞わせてるところが一番邪悪な感じがしますね。
Avatar
tarunon 07-Nov-17 05:58 AM
String?.none as? Int? => Int??.some(.none) こいつをウソのサブタイプを倒した後でどう説明するのが良いのか、どう言う振る舞いであるべきなのかを考えないといけない気がする
06:00
Cat?.none as Animal? これが暗黙のmapであるとするのであれば上の結果は正しいということになりますね
Avatar
koher 07-Nov-17 07:10 AM
String?.none as? Int? => Int??.some(.none)
これよくわからないんですが、 StringInt はパースですか?
Avatar
tarunon 07-Nov-17 07:10 AM
Avatar
koher 07-Nov-17 07:11 AM
ああ、 StringInt
Avatar
tarunon 07-Nov-17 07:11 AM
String?.none as? Int? ってやると結果が Int??.some(.none)になるんですよ。つまりキャストが成功する
Avatar
koher 07-Nov-17 07:11 AM
あれ?違った。
07:11
あー、そういうことか。
Avatar
Biacco42 07-Nov-17 07:11 AM
正しそう
Avatar
koher 07-Nov-17 07:12 AM
as?? を忘れてた。 (edited)
Avatar
tarunon 07-Nov-17 07:12 AM
[String]() as? [Int] これは 空配列になる。
Avatar
koher 07-Nov-17 07:13 AM
あー、要素全部キャストできたらルールがあるからか。
07:13
そのルール変だと思うんだけどなぁ。
Avatar
tarunon 07-Nov-17 07:14 AM
この2つは同じ問題の具象で、なので個人的には共変性はウソなのでは?という疑念を持っている
Avatar
Biacco42 07-Nov-17 07:19 AM
読み違えてた。キャストできちゃうの型としてはおかしいですね
Avatar
koher 07-Nov-17 07:24 AM
↓成功しないのおかしくないですか?
1> Int?.none as? Int? $R0: Int?? = nil
(edited)
Avatar
omochimetaru 07-Nov-17 07:24 AM
え!?
Avatar
tarunon 07-Nov-17 07:24 AM
.some(.none)も.noneもnilとして表示されます
07:24
なのでチェック用の関数作ってください
Avatar
omochimetaru 07-Nov-17 07:24 AM
なるほど!!!
Avatar
koher 07-Nov-17 07:24 AM
あ、そうなのか、
Avatar
hiragram 07-Nov-17 07:24 AM
nilリテラルわかりづらい
Avatar
omochimetaru 07-Nov-17 07:25 AM
おそらく .some(.none) なわけだ
Avatar
koher 07-Nov-17 07:25 AM
2> print(Int?.none as? Int?) Optional(nil)
07:25
大丈夫だった。
Avatar
omochimetaru 07-Nov-17 07:25 AM
1> dump(Int?.none as? Int?) ▿ Optional(nil) - some: nil $R0: Int?? = nil
07:25
dump便利
Avatar
koher 07-Nov-17 07:27 AM
↓がおかしいのか。
String?.none as? Int? // .some(.none)
Avatar
tarunon 07-Nov-17 07:27 AM
それがどうあるべきかということですね
Avatar
koher 07-Nov-17 07:27 AM
僕は .none であるべきだと思います。
Avatar
Biacco42 07-Nov-17 07:27 AM
desune
Avatar
omochimetaru 07-Nov-17 07:28 AM
空配列の互換性ルールから考えると .none になりそうですよね
Avatar
koher 07-Nov-17 07:28 AM
はい
07:28
なので
07:28
[String]() as? [Int] // .some([])
(edited)
07:28
これも .none であるべきかと
Avatar
tarunon 07-Nov-17 07:29 AM
Animal?.none as? Cat? ではこれは?
Avatar
omochimetaru 07-Nov-17 07:29 AM
あれ?そっち派?
Avatar
koher 07-Nov-17 07:29 AM
だって、全要素チェックとかおかしい気が。型の互換性だけを見るのがいいと思う。共変性は許すにしても。
07:30
あー、違うのか、値だから一度アップキャストしたらダウンキャストできなくなるのが問題なのか。
Avatar
tarunon 07-Nov-17 07:31 AM
でですね
07:31
([String]() as [Any]) as? [Int] (edited)
07:31
じゃあこれどうすんのという話になるわけです
07:32
なのでボクの立場としては共変性多分ウソなのでmap明記するようにしたい
Avatar
Biacco42 07-Nov-17 07:32 AM
Animal?.none as? Cat? ダメな気がしてきた
Avatar
koher 07-Nov-17 07:32 AM
let cats = [Cat]() let animals: [Animal] = cats // OK let cats2: [Cat] = animals as! [Cat] // これは?
(edited)
07:32
↑になってしまうのかぁ。
07:33
確かに共変性はウソなんだけど、
Avatar
omochimetaru 07-Nov-17 07:33 AM
そうですね、値型だから、実体共有はそもそも起きないから、都度都度の話になる
Avatar
koher 07-Nov-17 07:33 AM
let animals: [Animal] = cats // OK
↑ここで CoW を効かせたいからなぁ。
07:34
明示的に map すると先行コピーされちゃう。 (edited)
Avatar
omochimetaru 07-Nov-17 07:34 AM
なるほど。
Avatar
tarunon 07-Nov-17 07:34 AM
lazy sequenceでなんとかなんないですかね
Avatar
omochimetaru 07-Nov-17 07:34 AM
Arrayになるときにlazyを保てないような?
Avatar
koher 07-Nov-17 07:35 AM
アップキャストは共変っぽく働いて、ダウンキャストは明示的 map でもいい気も?
07:36
C# って値型とジェネリクスと変性がそろってるけどその辺りどうなってるの?
Avatar
omochimetaru 07-Nov-17 07:36 AM
C#は空でも別物扱いだった気がする、あとListは参照型じゃなかったかな
07:37
まともになったJavaって印象がある
Avatar
koher 07-Nov-17 07:37 AM
List は参照型だけど、値型+ジェネリクス+ out のときどうなるのかなって。
Avatar
omochimetaru 07-Nov-17 07:39 AM
普通に共変が効いた気がするけど曖昧です
07:39
ダウンキャストできないんじゃないかなあ・・・
Avatar
tarunon 07-Nov-17 07:40 AM
アップキャストは通るがダウンキャストは全てNG、これは筋が通ってそう
Avatar
omochimetaru 07-Nov-17 07:40 AM
07:40
wandboxにC#もあるっぽいです
Avatar
koher 07-Nov-17 08:02 AM
C#, interface しか out 付けれなかった。
using System; namespace HelloWorld { interface IBox<out T> { T Get(); } struct SBox<T> : IBox<T> { private T _value; public SBox(T t) { _value = t; } public T Get() { return _value; } } class CBox<T> : IBox<T> { private T _value; public CBox(T t) { _value = t; } public T Get() { return _value; } } class Animal {} class Cat : Animal {} class Hello { static void Main() { IBox<Cat> sCat = new SBox<Cat>(new Cat()); IBox<Animal> sAnimal = sCat; // OK sCat = (IBox<Cat>)sAnimal; // OK Console.WriteLine(sCat); IBox<Cat> cCat = new CBox<Cat>(new Cat()); IBox<Animal> cAnimal = cCat; // OK cCat = (IBox<Cat>)cAnimal; // OK Console.WriteLine(cCat); } } }
Avatar
omochimetaru 07-Nov-17 08:03 AM
なるほど・・・
Avatar
omochimetaru 08-Nov-17 02:07 AM
Swift版のgybを作ったんだけど、Swift4の文字列APIがいい感じだった。 https://github.com/omochi/gysb/blob/master/Sources/gysb/Parser.swift#L201-L209 あと enum Token がいい感じだった。 https://github.com/omochi/gysb/blob/master/Sources/gysb/Parser.swift#L51-L60 (edited)
gysb - Generate your swifty boilerplate
gysb - Generate your swifty boilerplate
Avatar
omochimetaru 09-Nov-17 02:39 AM
昨日の async void の人から長文が返ってきた https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20171106/041028.html
Avatar
tarunon 09-Nov-17 09:15 AM
async throws voidだったらどうするんだっていうの聞きたいな
Avatar
koher 09-Nov-17 02:30 PM
@tarunon 是非聞いて下さい〜🙃
Avatar
tarunon 09-Nov-17 02:42 PM
後で聞いてみます
Avatar
tarunon 10-Nov-17 09:39 AM
夜に送信したら送信先ミスってることに夜中に気づいて送信し直したんですよね
Avatar
koher 10-Nov-17 09:40 AM
しかし、元の beginAsyncthrows をなくそうという話への反応が少なくて悲しい。 Chris Lattner と Joe Groff の見解が知りたい。
Avatar
tarunon 10-Nov-17 09:40 AM
Void自体は存在していて、それはasync funcのタスク完了を意味するから言語仕様としてomitしてはいけない
Avatar
koher 10-Nov-17 09:41 AM
(Foo) async -> Void の戻り値を受けなくても別に問題ないですよね?
09:41
await foo() await bar() await baz()
09:41
単に foo の非同期処理が完了後 bar が実行され、 bar が完了後 baz が実行されるだけで。 (edited)
Avatar
tarunon 10-Nov-17 09:42 AM
はい。省略する分には構わないと思います。
Avatar
koher 10-Nov-17 09:42 AM
ああ、そういうことか。 < 言語仕様として
09:42
async -> Void ができなきゃいけないって意味ですね。
Avatar
tarunon 10-Nov-17 09:43 AM
そうです
Avatar
koher 10-Nov-17 09:45 AM
beginAsyncthrows について反応がないのはなんでなんだろう?静的チェックの安全性を壊すか壊さないかの重要な話だと思うんですけどねぇ・・・。
09:45
英語がひどすぎて読めないのかな?😂
😫 1
Avatar
omochimetaru 11-Nov-17 05:12 AM
class Cat { func nya(_ a: Int) -> String { return String(a) } } let nya: (Cat) -> (Int) -> String = Cat.nya let cat = Cat() nya(cat)(3) // "3" Cat.nya(cat)(4) // "4"
05:13
型名からメソッド名を参照すると、レシーバについてカリー化された関数の型になっているの、知らなかった。
Avatar
rintaro 11-Nov-17 12:11 PM
https://github.com/apple/swift-evolution/blob/master/proposals/0042-flatten-method-types.md 一応仕様変更予定です。が、Swift3に間に合わなかったので再考の必要あるとTedがMLで発言していた記憶あります。
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
omochimetaru 11-Nov-17 12:21 PM
ああ、このプロポーザル眺めた記憶が出てきた
Avatar
omochimetaru 14-Nov-17 02:32 AM
- Indices.swift.gyb + Indices.swift
02:32
おー、 CondConfでgybが一つ減る
Avatar
norio_nomura 14-Nov-17 02:32 AM
これは4.1へ入ると期待していいのかしらん?>Conditional Conformance (edited)
Avatar
omochimetaru 14-Nov-17 02:32 AM
もう機能はできててガンガンstdlibに適用してるフェーズですかね?
Avatar
koher 14-Nov-17 02:33 AM
CountableRange 系の削除に期待。
Avatar
omochimetaru 14-Nov-17 02:33 AM
それがあった
Avatar
tarunon 14-Nov-17 02:34 AM
gybかなり減りそう
Avatar
omochimetaru 14-Nov-17 02:34 AM
Generics系の機能が一つ入るたびにgybの需要が一つ減るからね
Avatar
koher 14-Nov-17 02:34 AM
Conditional Conformance で CountableRange 消す PR 書くの気持ち良さそう。
Avatar
rintaro 14-Nov-17 02:37 AM
https://swift.org/blog/swift-4-1-release-process/ によると 11/27 がデッドラインかと。大きなバグが見つかったら4.1ブランチだけで機能 disable の可能性はあるにせよ。
This post describes the goals, release process, and estimated schedule for Swift 4.1.
Avatar
norio_nomura 14-Nov-17 02:37 AM
やっぱり厳しそうですよね。
02:40
Conditional Conformance自体は書けるけどstdlibは書き直されていない、な状態で入る可能性もあるのかな? (edited)
Avatar
rintaro 14-Nov-17 02:43 AM
過去にそういう事例はあった気がする。
Avatar
norio_nomura 14-Nov-17 08:47 AM
難しそう。>Conditional Conformance自体は書けるけどstdlibは書き直されていない
08:50
CodableとかAPI自体を見直さないとダメそう。>Conditional Conformance (edited)
Avatar
norio_nomura 14-Nov-17 09:01 AM
import Foundation struct S<Wrapped> { var value: Wrapped } extension S: Codable where Wrapped: Codable { enum CodingKeys: String, CodingKey { case value } init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) value = try container.decode(Wrapped.self, forKey: .value) } func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(value, forKey: .value) } } let s = S<Int>(value: 1) let encoder = JSONEncoder() let data = try encoder.encode(s) print(String(data: data, encoding: .utf8)!) // {"value":1}
swift-DEVELOPMENT-SNAPSHOT-2017-11-13-aで動いた。
👏 2
Avatar
koher 14-Nov-17 09:02 AM
おおお
09:02
ついに Conditional Conformance な世界が触れるようになるんですね。
Avatar
norio_nomura 14-Nov-17 09:07 AM
extension S: Sequence where Wrapped: Sequence { func makeIterator() -> Wrapped.Iterator { return value.makeIterator() } }
はコンパイラクラッシュ
Avatar
koher 14-Nov-17 09:11 AM
なるほど。まだまだ開発中な感じなんですね。たしかに SequenceElement, Iterator, SubSequence とあって、それらが関係しているので複雑そうです。
09:12
↑の Wrapped.Iterator を自分の Iterator として解決する辺りとかヤバそう。
Avatar
norio_nomura 14-Nov-17 09:35 AM
Conditional Conformanceが入ると[Any]Codableでは無くなる?
Avatar
koher 14-Nov-17 09:36 AM
そうだと思ってます。
09:36
extension Array: Codable where Element: Codable {}
かと。
09:37
Equatable とかと同様に。
Avatar
norio_nomura 14-Nov-17 09:37 AM
[AnyHashable: Any]も。
Avatar
norio_nomura 15-Nov-17 03:37 AM
[String: Any]の代わりに[String: Codable]を使っても、Encoder,Decoder側に扱うAPIが無いかも。
Fatal error: Dictionary<String, Decodable & Encodable> does not conform to Encodable because Encodable does not conform to itself. You must use a concrete type to encode or decode.
Avatar
koher 15-Nov-17 03:39 AM
extension Dictionary: Codable where Value: Codable {}
が必要な気がします。正確には EncodableDecodable 別々に。
03:39
あー、キーもか
03:39
extension Dictionary: Codable where Key == String, Value: Codable {}
こうかな?
Avatar
norio_nomura 15-Nov-17 03:45 AM
そうではなくて、AnyCodableみたいなものが必要なんじゃないかな?と。
Avatar
koher 15-Nov-17 03:47 AM
CodableassociatedtypeSelf も持たないだたの protocol だから、 Codable 型として existential になりますよね?
struct Foo: Codable {} let foo: Codable = Foo() // OK
Avatar
omochimetaru 15-Nov-17 03:48 AM
Existentialそれ自体はそのプロトコルを満たさないからそれで取り回すと不便な事が多いですよ
Avatar
norio_nomura 15-Nov-17 03:48 AM
そう、それがさっきのエラーメッセージに書かれていたこと。> You must use a concrete type to encode or decode. (edited)
Avatar
omochimetaru 15-Nov-17 03:49 AM
protocol P0 { } struct A : P0 {} func f<X: P0>(_ x: X) {} var a: P0 = A() f(a) // error
Avatar
norio_nomura 15-Nov-17 03:50 AM
EncodingContainer達にも、<T: Encodable>を受けるAPIはありますがEncodableを直接受けるAPIは無いです。
Avatar
omochimetaru 15-Nov-17 03:51 AM
ですね。
Avatar
koher 15-Nov-17 03:51 AM
なるほど。
Avatar
norio_nomura 15-Nov-17 03:54 AM
Swift.Codersの実装PRにも「内部でダイナミックキャストが必須なのであれば、<T: Encodable>ではなくEncodableを直接受け取れば良いのでは?」とコメントしたのですが、受け入れられませんでした。
Avatar
omochimetaru 15-Nov-17 03:54 AM
ほお・・・
Avatar
koher 15-Nov-17 03:56 AM
これって Generalized Existential で AnySequence がなくせる話と絡んで、 Any<Codable> とかできるようになるのかな?
Avatar
omochimetaru 15-Nov-17 03:56 AM
そう思います
Avatar
koher 15-Nov-17 03:57 AM
プロトコル型がそのプロトコルを満たさないのってなんでなんだっけ?
Avatar
omochimetaru 15-Nov-17 03:58 AM
それは僕も疑問、仕組みだけで言えば満たせると思う。全部の機能をちょうど持ってるから。 (edited)
Avatar
koher 15-Nov-17 04:02 AM
↓はできるのか。
1> let a: Any = 42 a: Int = 42 2> func foo<T: Any>(_ x: T) { print(x) } 3> foo(a) 42
Avatar
norio_nomura 15-Nov-17 04:03 AM
PRではなくJIRAだった。 https://bugs.swift.org/browse/SR-5206?focusedCommentId=25786&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-25786 Encodableではなく<T: Encodable>なのは、decode()側が<T: Decodable>を使う必要があり、そちらと一貫性を持たせる為だと言われた。
Avatar
tarunon 15-Nov-17 11:41 AM
よさそうですね! んで、 `Animal` が`bark()` メソッドをもってるとして、`Any<Animal>` 型の`animal` に対して `animal.bark()` を呼びだせるのは`Any<Animal>: Animal` なわけではなく、 Opening existentials のシンタックスシュガーだって考えればよさそう? let animal: Any<Animal> = Dog() // OK animal.bark() // ↑は以下のシンタックスシュガー // aの型はA。AはAnimalに準拠。 let a = animal openas A a.bark()
@ukitaka 前結局理解できなかったのだけどAny<Animal>がAnimalのextentialでなくなる理由とか嬉しい点って何ですか?
11:42
この話とAnimal protocolがAnimalのextentialじゃなくなる話が多分同じはず
Avatar
ukitaka 15-Nov-17 12:21 PM
Any<Animal>がAnimalのextentialでなくなる理由
12:23
説明が難しいんですが、一言で言うと存在型の理論そのままいくとそうなるって感じです。内部的にはいまもopenas ↑の動きになってますね
12:24
型チェックの段階でopening existentialが入ってます
Avatar
tarunon 15-Nov-17 12:25 PM
今もそうなんじゃないかと直感していて、じゃあ現状のprotocol変数は存在型として実装されていて、理論があってということ
12:25
理論を理解しないと先に進めないか
12:26
とすると、 Animal.self こいつは存在型の型で (edited)
12:26
Animal.self is Animal.Typeはfalseになるのが正しい?
Avatar
ukitaka 15-Nov-17 12:27 PM
存在型へのpack/unpackが暗黙的に行われているのでサブタイプっぽく振る舞えるのがややこしくしている原因かなと思います。
12:27
Animal.self is Animal.Typeはfalseになるのが正しい?
12:27
Self: Animal って意味ならtrueが正しいです (edited)
Avatar
tarunon 15-Nov-17 12:30 PM
えーっと、ArrayとOptionalの変性はめちゃくちゃなので無視するとして
12:31
func foo<T: SomeProtocol>(...) これに対して、Tの型はかなりカッチリしていて
12:32
ちゃんとSomeProtocolを実装した型じゃないと通らない。SomeProtocolの存在型は変数ではキャスト可能(に見える)が型としてはダメなので通らない正解.というわけ
12:33
T:AnyObjectの時にTにStringが通らないのと同じか。
12:34
@ukitaka 理論は後回しにして挙動と斯くあるべきかは理解できました、ありがとう。
👌 1
Avatar
ukitaka 15-Nov-17 12:45 PM
foo<T: SomeProtocol>(t: T)とfoo(t: SomeProtocol)の話で言えばこんな感じですね
Avatar
omochimetaru 15-Nov-17 12:48 PM
let a = animal openas A // 将来opening existentialが入るとする
12:48
このときの a の型ってなんですか?
Avatar
ukitaka 15-Nov-17 12:48 PM
Aです
Avatar
omochimetaru 15-Nov-17 12:49 PM
それは test2 の型パラメータの <A> と同じって意味?
Avatar
ukitaka 15-Nov-17 12:49 PM
あ、いやなにかわからないけどA: AnimalなAという意味です。
Avatar
koher 15-Nov-17 12:50 PM
Existentialだからサブタイプじゃないってことですか?でも Genralozed Existentialが導入されたらExistentialを使ってAnySequence (= Sequence のサブタイプ) を作りたいわけですよね??
Avatar
ukitaka 15-Nov-17 12:53 PM
うーん、AnySequenceは、Self: Sequenceな型であって、AnySequence: Sequenceではないって感じですかね。。
Avatar
koher 15-Nov-17 12:57 PM
書きたいことがあるんですが今スマホなので後ほど…
Avatar
koher 15-Nov-17 01:49 PM
↑の件です。 まず、↓はできません。
protocol Animal {} struct Cat: Animal {} func bar<T: Animal>(_ x: T) { print(x) } let b: Animal = Cat() bar(b) // NG
(edited)
13:49
しかし、↓はできます。
func foo<T: Sequence>(_ x: T) { print(x) } let a: AnySequence<Int> = AnySequence([2, 3, 5]) foo(a) // OK
(edited)
13:50
そして、 Generalized Existential が実現されたら↓になることが示唆されています。
typealias AnySequence<Element> = Any<Sequence where .Iterator.Element == Element>
https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md#generalized-existentials
(edited)
swift - The Swift Programming Language
13:51
そうすると、現状との互換性を考えると当然 fooAny<Sequence where .Iterator.Element == Element> という Existential Type を渡せるということになります。
13:52
ここで、 Existential をサブタイプとして振る舞わせるのであれば、 Animalbar に渡せてもいいように思うのですがいかがでしょう?
Avatar
ukitaka 15-Nov-17 01:56 PM
たしかに...渡せたほうがよさそうですね > 現状との互換性を考えると
13:57
その場合はAnimalをbarに渡したときにも型チェック時にopening existentialが挿入されるようになるとかですかねぇ〜
Avatar
koher 15-Nov-17 01:59 PM
確かに今は型パラメータは具体的な型で埋められるので、どういう扱いになるのか謎ですね🤔
Avatar
norio_nomura 16-Nov-17 11:49 AM
これのremove()実装、1個づつmoveInitialize()してるけど、まとめて出来るはず。 https://qiita.com/omochimetaru/items/f32d81eaa4e9750293cd
Swift の Array や Dictionary は Copy on Write になっていてとても使いやすいです。この記事では、そのような Copy on Write の実装方法を解説します。 # CoW の動作 Copy ...
Avatar
omochimetaru 16-Nov-17 10:05 PM
おっ、そんな細かいところまで、見てくれてありがとうございます
22:06
ちゃんと一個ずつずらしてやってくれるんですかね?
22:06
この手のAPI、メモリ領域が重なってても期待通りに動くことがあったり動かなかったりするので避けました。
22:07
インデックスが若い順に1つずつ処理されるなら大丈夫そうだけど、インデックスが後ろからやるかもしれないとか。
Avatar
lovee 17-Nov-17 01:30 AM
そもそもSwiftのArrayの removeSubrange も O(n) だからいいじゃないかなと思ったりする https://developer.apple.com/documentation/swift/array/2884498-removesubrange
Avatar
omochimetaru 17-Nov-17 01:31 AM
moveInitialize にしても O(n) なのは変わらないですね でも、ループを自分でやるより関数に畳み込むほうが最適化も期待できるし、コードはシンプルにできるので、ちゃんと動くなら書き換えたほうが良さそう。
Avatar
lovee 17-Nov-17 01:32 AM
当たり前っちゃ当たり前だけど、remove 系のメソッド全部確認して見たらやはりremoveLast だけ O(1) だった
Avatar
norio_nomura 17-Nov-17 01:33 AM
swift - The Swift Programming Language
Avatar
omochimetaru 17-Nov-17 01:35 AM
あっ
01:35
左から右か右から左か
01:35
アドレスで分岐するのかw
01:35
かしこいな
01:35
/// - source: A pointer to the values to copy. The memory region /// `source..<(source + count)` must be initialized. The memory regions /// referenced by `source` and this pointer may overlap.
01:35
source and this may overlap だから
01:36
オーバーラップもオッケーだ
Avatar
omochimetaru 17-Nov-17 01:49 AM
更新しました。
Avatar
tarunon 21-Nov-17 12:45 AM
いつぞやのfilterMap、acceptedになってた (edited)
00:45
Forced Reviewってなんぞや
Avatar
rintaro 21-Nov-17 12:46 AM
focused re-review で、名前だけ再考するってことかと。
Avatar
tarunon 21-Nov-17 12:47 AM
flatMapのオーバーロードが危険なのは間違いないから分けるとして、分割先のメソッド名は考えましょうってことですか?
Avatar
rintaro 21-Nov-17 12:48 AM
んだ。
We are re-opening the review until next Monday, November 20th, 2017, in order to have a focused discussion about the new name.
Avatar
tarunon 21-Nov-17 12:50 AM
Focusedだった、完全に空目でした. 🙈
Avatar
koher 24-Nov-17 02:42 AM
ExpressibleByRegularExpressionLiteral を話してる中で Chris Lattner が↓言ってるんですがおもしろくないですか?
2) I’d like to explore the idea of making // syntax be *patterns* instead of simply literals. As a pattern, it should be possible to bind submatches directly into variable declarations, eliminating the need to count parens in matches or other gross things. Here is strawman syntax with a dumb example: if case /([a-zA-Z]+: let firstName) ([a-zA-Z]+: let lastName)/ = getSomeString() { print(firstName, lastName) }
Avatar
omochimetaru 24-Nov-17 02:42 AM
げっ、なんだこりゃっ
02:43
正規表現リテラルをただ入れるだけじゃなくて、正規表現リテラルと言語を合体させて、内側に let があるのか。
02:43
すごいアイデア
02:43
あ、パターンマッチのマッチと
02:43
regexのマッチが
02:43
同時に成立するのか。
Avatar
koher 24-Nov-17 02:44 AM
正規表現の表現力って一般的なパーサのサブセットだと思うんだけど、標準ライブラリにパーサコンビネータ的なものを入れて、正規表現リテラルからそれを組み立てることで一本化するとかできないかな? (edited)
Avatar
omochimetaru 24-Nov-17 02:44 AM
繰り返しパターンとかのときってうまくいくんだろうか
02:45
パーサコンビネータと正規表現って実装技術や理論体系が結構違うはずだから難しそう
Avatar
koher 24-Nov-17 02:46 AM
できたとしてもパフォーマンスが出ない?
Avatar
omochimetaru 24-Nov-17 02:46 AM
パーサコンビネータがParseqみたいな「Packrat Parsing」をさすならだけど。
Avatar
t.ae 24-Nov-17 02:46 AM
あとでグループから読むのは面倒だと思ってましたが直接書けるのも長くなりそうな……
Avatar
omochimetaru 24-Nov-17 02:47 AM
できたとしてもパフォーマンスが出ない?
とおもいます
Avatar
koher 24-Nov-17 02:52 AM
たとえばだけど、構文適当だけど正規表現を文字列以外に拡張して↓みたいなことができるとか。
let sortedScores: [Int] = ... if case /([\(0)-\(59)]+: let 不可)([\(60)-\(69)]+: let 可)([\(70)-\(79)]+: 良)([\(80)-\(100)]: let 優)/ = sortedScores { print("優: \(優.count)人") print("良: \(良.count)人") print("可: \(可.count)人") print("不可: \(不可.count)人") }
Avatar
koher 27-Nov-17 07:06 AM
↓正式な evolution のプロセスに乗りそう。 https://github.com/apple/swift-evolution/pull/768
This proposal introduces a new DynamicMemberLookupProtocol type to the standard library. Types that conform to it provide "dot" syntax for arbitrary names which are resolved at runtime. It is usef...
Avatar
koher 27-Nov-17 07:14 AM
a = someValue.someMember someValue.someMember = a mutateParameter(&someValue.someMember)
a = someValue[dynamicMember: "someMember"] someValue[dynamicMember: "someMember"] = a mutateParameter(&someValue[dynamicMember: "someMember"])
(edited)
07:15
この変換って、 Swift のメンバーとしてパースできないものは使えない?
07:16
たとえば、 Ruby の
a = [2, 3, 5] a.empty?
とか。
Avatar
rintaro 27-Nov-17 07:32 AM
subscript(dynamicMember:) 内で適宜書き換えてあげないとだめっぽいですね。 (edited)
Avatar
koher 27-Nov-17 08:10 AM
あー、↓の例がたまたま add_trick のままなだけで、 PyValsubscript で読み替える実装にすれば addTrick にもできるわけですね。
// import DogModule // import DogModule.Dog as Dog // an alternate let Dog = Python.import("DogModule.Dog") // dog = Dog("Brianna") let dog = Dog("Brianna") // dog.add_trick("Roll over") dog.add_trick("Roll over")
(edited)
08:10
ん??シンタックスハイライトが壊れた。
Avatar
tarunon 27-Nov-17 08:55 AM
let Dog = Python.import(DogModule.Dog")
👍 1
Avatar
koher 27-Nov-17 09:02 AM
そういえばこの " のコピペ問題、 @rintaro さんとハッカソンやったときに多発してた気がする。
Avatar
tarunon 27-Nov-17 09:02 AM
Appleの提供する最強のうんち仕様が一、「スマート引用符」ですよ
09:03
何もスマートじゃない
09:03
Preferences -> Keyboard -> Text -> Use smart quotes and dashesをDisableでOk
🙏 1
09:03
でもこれアプリごとにゾンビみたいに復活して苦しめられる記憶があります
Avatar
omochimetaru 27-Nov-17 09:04 AM
“□” U+201C (8220) , U+201D (8221)
09:05
Swiftコンパイラなら201Cと201Dの検出機能が入ってるからダイジョーブ😇
Avatar
tarunon 27-Nov-17 09:05 AM
09:06
逆にこの設定で全部""にしたほうが安全では??
09:06
おお
09:06
いける、いけるぞ!!
Avatar
rintaro 27-Nov-17 09:08 AM
コピペで多発したのは SOFT HYPHEN(U+00AD) かな? https://github.com/swift-script/swift-script/pull/18 Apple のドキュメントをコピペすると入ってる時がある。
Avatar
koher 27-Nov-17 09:09 AM
あー、 soft hyphen でしたね。
09:09
soft hyphen も凶悪だ・・・。
Avatar
koher 28-Nov-17 08:01 AM
もしかして subscript には @_specialize が許可されてない?
struct Foo { @_specialize(where T == Int) // OK func foo<T>(_ x: T) -> T { return x } @_specialize(where T == Int) // Error subscript<T>(x: T) -> T { return x } }
(edited)
08:02
subscript は元々ジェネリックじゃなかったけど、ジェネリックになったときに対応忘れたとか? (edited)
Avatar
rintaro 28-Nov-17 09:12 AM
_ つきだから、 stdlib で使用する要求が無いと実装されないかもしれないですね。
Avatar
koher 28-Nov-17 09:13 AM
なるほど。
Avatar
rintaro 28-Nov-17 09:17 AM
https://github.com/apple/swift/blob/603e5359fd534117c452adeccf10d04624ddab70/include/swift/AST/Attr.def#L172-L174 ここに OnSubscript を足せばそのエラーの先には行けます。
swift - The Swift Programming Language
Avatar
koher 28-Nov-17 09:18 AM
おお、そんな形で管理されてるんですね。
09:19
前に話してた cross module specialization ってどうなったんでしたっけ?
09:19
結局 Proposal にならず??
Avatar
rintaro 28-Nov-17 09:20 AM
最近追えてないっす。
Avatar
koher 28-Nov-17 09:21 AM
スレッドチェックしたら 10/8 で止まってますね・・・
09:24
@_specialize と言えば、昨日過去最多の @_specialize をつけました・・・。 https://github.com/koher/EasyImagy/blob/dev-0.4.0/Sources/EasyImagy/ImageSpecialized.swift#L2-L677
EasyImagy - Makes it easy to deal with images in Swift
👀 1
Avatar
omochimetaru 28-Nov-17 09:24 AM
やべえw
Avatar
koher 28-Nov-17 09:25 AM
世界中探してもこんなに @_specialize の付いてるコードは見つけられないかもしれないw
Avatar
t.ae 28-Nov-17 09:27 AM
Numeric一通り対応するだけで組み合わせるとすごい数になりますからね 早くクロスモジュール最適化が欲しい
Avatar
koher 28-Nov-17 09:28 AM
そのNumericが RGBA で倍増して、それを組み合わせたのでこんなことに・・・。 (edited)
09:29
早くクロスモジュール最適化が欲しい
それが 10/8 でスレ止まってるし、 Proposal も出てないっぽいです。
Avatar
omochimetaru 28-Nov-17 09:30 AM
前のメールは正規のやつじゃなくて意見募集だったから、今提案をまとめてるのだろうか
Avatar
koher 28-Nov-17 09:30 AM
スレッドの最後で Chris Lattner と Joe Groff がやりとりしてるっぽかった。
09:31
伸びすぎてて中身はチェックしてません。
Avatar
rintaro 28-Nov-17 10:12 AM
cross module specialization で提案されている @inlineable って @_inlineable として既に実装されているような?
Avatar
omochimetaru 28-Nov-17 10:12 AM
そんな雰囲気でしたよ
10:12
_ を外して正規仕様にするために提案を整理してるけど内容は現状あるやつ
10:12
みたいな感じで。
10:13
あと private なメソッドでも インライン化したい件については、 @inlineable ではできないけど、現状 @_versioned でできてるから、これは別の提案で出す、とか。
10:13
こっちは @_versioned はわかりにくいから別の名前が良いって意見があった
Avatar
rintaro 28-Nov-17 10:15 AM
@_inlineable も最初 @_fragile だった。いずれにしてもパッとは分からないですねー。
Avatar
rintaro 29-Nov-17 12:47 AM
Conditional conformances aren't quite ready yet for Swift 4.1, so introduce the flag -enable-experimental-conditional-conformances to enable conditional conformaces, and an error when one declares ...
Avatar
tarunon 29-Nov-17 12:47 AM
グエー
Avatar
omochimetaru 29-Nov-17 12:48 AM
😲
Avatar
ikesyo 29-Nov-17 12:49 AM
でもまあフラグ指定で使えるのであれば……
Avatar
tarunon 29-Nov-17 12:50 AM
ちょっと小難しいことやると壊れそう
Avatar
norio_nomura 29-Nov-17 12:58 AM
やはり
Avatar
koher 29-Nov-17 01:19 AM
😢
Avatar
koher 29-Nov-17 07:36 AM
↓こんなの見つけた。バグでは?
1> let a = [2, 3, 5] a: [Int] = 3 values { [0] = 2 [1] = 3 [2] = 5 } 2> let f: (Int) -> Int = a.subscript Segmentation fault: 11
Avatar
Kishikawa Katsumi 29-Nov-17 07:36 AM
Segmentation faultは明らかにバグですね
Avatar
koher 29-Nov-17 07:37 AM
ですよね。
Avatar
omochimetaru 29-Nov-17 07:37 AM
コードがオモロイ
Avatar
lovee 29-Nov-17 07:37 AM
本当だ
Avatar
koher 29-Nov-17 07:38 AM
Avatar
rintaro 29-Nov-17 07:38 AM
4.1 で直るはず。チョット待ってくださいね。
Avatar
koher 29-Nov-17 07:38 AM
おお、そうなんですね。
07:39
4.1 ということは春か。それまでクロージャ式でラップするか。
Avatar
hiragram 29-Nov-17 07:39 AM
subscriptもそういう使い方できるんだ…
Avatar
rintaro 29-Nov-17 07:39 AM
07:41
subscriptもそういう使い方できるんだ…
いいえ。できないです。 master だと
error: value of type '[Int]' has no member 'subscript' let f: (Int) -> Int = a.subscript ^ ~~~~~~~~~
Avatar
hiragram 29-Nov-17 07:41 AM
ああ。
07:41
本来はコンパイルエラーになるべきということですね。
Avatar
koher 29-Nov-17 07:41 AM
@rintaro さんが 1 年以上前に通ってた・・・。
Rintaro Ishizaki added a comment - 15 Sep 2016 4:51 AM Minimum repro: class C { subscript(x: Int) -> Void { return } } _ = C().subscript
07:42
subscript のリファレンスを取る方法は封じられたんでしたっけ? (edited)
07:42
しかも、さっき検索したリストの下の方にこのバグレポート出てた。検索力が足りない😂
Avatar
rintaro 29-Nov-17 07:43 AM
知ってる限り、 subscript のリファレンスは取れないですねー。
Avatar
koher 29-Nov-17 07:43 AM
ありがとうございます〜🙇
Avatar
rintaro 29-Nov-17 07:52 AM
class C { subscript(x: Int) -> Void { print(x) } } let idx = 12 let kp = \C.[idx] C()[keyPath: kp]
keypath はインデックス固定のリファレンスと見れなくもないか? やりたいこと逆ですがw
Avatar
koher 29-Nov-17 07:53 AM
今、 (Int) -> Element として高階関数に渡したいので😅
Avatar
omochimetaru 06-Dec-17 12:18 AM
おーマージされたね https://github.com/apple/swift/pull/13273
This pr is improvement of comment. Seems SomeEnumWithAssociatedValues implements require result initial value.
👍 2
🎉 10
✌ 1
Avatar
omochimetaru 06-Dec-17 06:26 AM
06:28
Streamが長いと購読解除のスタックトレースが深い・・・
Avatar
tarunon 06-Dec-17 06:42 AM
それはもう必然やね
Avatar
omochimetaru 06-Dec-17 06:44 AM
テーブルビューのセルがリサイクルされるときに
06:44
セルとモデルはflatMapLatestの内部で古い方を解除して新しい方を接続するんだけど
06:44
そこで時々プチフリーズしていてプロファイルとったら↑が出てきた
Avatar
tarunon 06-Dec-17 08:18 AM
Type-erasureに再帰的に詰めてるところ、ズルはできないかな?
Avatar
omochimetaru 06-Dec-17 08:18 AM
継承にしたら1段減らせると思ったんだけど
Avatar
tarunon 06-Dec-17 08:18 AM
例えばRxSwiftではObservable.mapはちょっとだけズルをしていて、Map.mapがズルい実装になっています
Avatar
omochimetaru 06-Dec-17 08:18 AM
そうすると init で別の実装を差し込むことができなくて、例の技を使う必要が出てくるんだけど
08:19
一般のサブクラスでDog漏れが生じて終わった
Avatar
tarunon 06-Dec-17 08:19 AM
そこでclass + convertible protocolですよ
Avatar
omochimetaru 06-Dec-17 08:19 AM
RxSwiftのずるってどういうズル?
08:19
イレイジャーの中にあるbaseを触るとか?
Avatar
tarunon 06-Dec-17 08:20 AM
RxSwift - Reactive Programming in Swift
👀 1
08:20
RxSwiftのObservableはまさに、class + convertible protocolの作りになっていて
08:20
ユーザーランドではsubclassを作れない、代わりにconvertible protocolが使える
Avatar
omochimetaru 06-Dec-17 08:20 AM
なんだこれは、mapオペレータの内臓を取り出してる?
Avatar
tarunon 06-Dec-17 08:21 AM
えっと、mapの実態はcomposeMapなんだけど
08:21
Mapはそれをオーバーライドしていて不要なスタックが増えるのを防いでいる
Avatar
omochimetaru 06-Dec-17 08:21 AM
ほんとだ override だ
Avatar
tarunon 06-Dec-17 08:22 AM
Disposableのスタックが増えて困るなら、そうだね
08:22
DisposableとDisposableConvertibleを作って
08:22
public class Disposable: DisposableConvertibleにしてユーザー側ではサブクラス作れないようにする (edited)
08:22
オレオレ作りたい人はDisposableConvertibleを使う、とやると解決しそう
Avatar
omochimetaru 06-Dec-17 08:24 AM
RxSwift - Reactive Programming in Swift
08:25
これとか、 Disposables.create になっているけど、
08:25
これを Disposable.init() にしたかったんだよね
Avatar
tarunon 06-Dec-17 08:25 AM
うむ
Avatar
omochimetaru 06-Dec-17 08:25 AM
(複数形じゃなくて本体の名前で、かつ、init)
Avatar
tarunon 06-Dec-17 08:25 AM
RxSwiftはクラスクラスタではないからDisposablesというUtilを使っているね
08:26
Disposables、JavaにおけるArraysみたいな感じで複数系ではなくUtilクラスの意味だとおも
08:26
Lists?なんかsのつくUtilあったよね
Avatar
omochimetaru 06-Dec-17 08:26 AM
いろいろあるね
08:27
// this is kind of ugly I know :( // Swift compiler reports "Not supported yet" when trying to override protocol extensions, so ¯\_(ツ)_/¯ /// Optimizations for map operator internal func composeMap<R>(_ transform: @escaping (Element) throws -> R) -> Observable<R> { return _map(source: self, transform: transform) }
Avatar
tarunon 06-Dec-17 08:28 AM
w
Avatar
omochimetaru 06-Dec-17 08:28 AM
この _map ってどこに定義されてるんだ?
Avatar
omochimetaru 06-Dec-17 08:29 AM
なるほど
08:29
つまり、 map オペレータに関しては
08:30
一般のObservable を扱う実装じゃなくて、一般のやつはObservable で実装してあって、一部のサブクラスではオーバライドして最適化してる?
Avatar
tarunon 06-Dec-17 08:30 AM
一部というかMapだけ
08:32
public class Disposable { public init() { // ここはクラスクラスタ } } private class CompositeDisposable: Disposable {} // ... その他諸々 protocol DisposableConvertible { var asDisposable: Disposable { get } } public extension Disposable: DisposableConvertible { var asDisposable: Disposable { return self } }
Avatar
omochimetaru 06-Dec-17 08:33 AM
その場合さ、CompositeDisposableを使いたいユーザーはどうしたらいいかな
Avatar
tarunon 06-Dec-17 08:33 AM
こうするとユーザが拡張Disposable作るときはDisposableConvertibleを使って実装することになる。 基本的にはDisposableConvertibleでやり取りしていればおk
08:34
Disposableのinitのパターンを増やす
Avatar
omochimetaru 06-Dec-17 08:34 AM
Compositeの場合は一個ずつaddとかがやりたい場合がある
Avatar
tarunon 06-Dec-17 08:34 AM
後から追加する場合か
08:35
うーん、まあクラスタのメンバーは必ずしもprivateじゃなくていいんじゃない?
08:35
必要に応じて見えてていいと思う
Avatar
omochimetaru 06-Dec-17 08:35 AM
いやそうすると
08:35
CompositeDisposable.init() // NopDisposable用のfactory init
08:35
CatにみえるDog問題が出てくる
Avatar
tarunon 06-Dec-17 08:35 AM
overrideしてunavailableつけれない?
Avatar
omochimetaru 06-Dec-17 08:35 AM
その手があったか
Avatar
tarunon 06-Dec-17 08:36 AM
兎角Disposableをopenにしなければなんとかなるはず
Avatar
omochimetaru 06-Dec-17 08:38 AM
RxSwiftのObservableConvertibleTypeって
08:38
実装は各自でやって、ってなっていて
08:39
ObservableType : ObservableConvertibleType は、実装をもっていたけど
08:39
ObservableTypeとObservableConvertibleTypeに分けておく嬉しさはどこにあるん
Avatar
tarunon 06-Dec-17 08:39 AM
そこは俺は知らない
Avatar
omochimetaru 06-Dec-17 08:40 AM
なるほど
Avatar
tarunon 06-Dec-17 08:40 AM
ObservableTypeとObservableConvertibleType、型パラの指定で使い方が違うから
Avatar
omochimetaru 06-Dec-17 08:40 AM
今の自分の設計だと、 protocol DisposerProtocolとclass Disposerがあって、Disposerは init<X: DisposerProtocol>(_ base: X) なイレイジャーにしてあって、 DisposerProtocol は extension で asDisposer() -> Disposer を持たせていて
Avatar
tarunon 06-Dec-17 08:41 AM
そうすると無限にスタックが積まれるね
Avatar
omochimetaru 06-Dec-17 08:41 AM
一般にこの XxxProtocolと Erasure用の Xxx の2つがあればいけそうにおもうんだけど
08:42
うん。あーそこがうまいことできるのか?
08:42
いや、Disposer自身の asDisposer() は return self だから、真の型が Disposerの時はそこで止まるけどね
Avatar
tarunon 06-Dec-17 08:42 AM
Erasureだけだと、Erasureが多重化するパターンがしんどいから
Avatar
omochimetaru 06-Dec-17 08:42 AM
静的に見えてる場合だけだけど。
Avatar
tarunon 06-Dec-17 08:42 AM
あれ、そこはうまくいってるのか
08:42
動的にそこが解決できるとスタックネストしないように出来ないかな
08:43
動的にする最短ルートがクラスクラスタの気もするけど
Avatar
omochimetaru 06-Dec-17 08:43 AM
プロパティとかではDisposer で保持して 引数では DisposerProtocol で受けてるから保持する直前には真の型が見えててうまくいく (edited)
08:45
08:45
Convertible自分でもやってたわ、EventSinkProtocolとEventSinkConvertibleを作っていた
08:45
Convertibleは メソッド名を固定してないんだ。
08:46
ああ、RxSwiftのObservableも同じっぽい
08:46
ObservableType は subscribe が生えてるから、 subscribe メソッドをラップして Observable に erase する動作がデフォルト提供されてるけど
Avatar
tarunon 06-Dec-17 08:46 AM
ああ、そうだね
08:47
それはそうなんだけど、僕はそれが別れていて何が嬉しいのかがよくわかってない
08:47
間の型の必要性が良くわかってないな
08:47
classとconvertibleだけでいけるのでは?と思っている
Avatar
omochimetaru 06-Dec-17 08:48 AM
ObservableConvertibleType は subscribe じゃないメソッドで Obserbable化したい場合にそなえてrんだ
08:48
ああ、そっちか。
08:48
それは、ユーザーが、継承じゃない形で ObservableType を実装できるようになってるんじゃないか
08:49
ああ、その場合もConvertibleでいけばいいってことね
Avatar
tarunon 06-Dec-17 08:49 AM
そう
Avatar
omochimetaru 06-Dec-17 08:49 AM
まあsubscribeメソッドが補間で出てくるから少し温かいのでは・・・
08:49
Convertibleはsubscribeメソッドの概念は持ってないから。
Avatar
tarunon 06-Dec-17 08:49 AM
いやでも
08:49
あーーー
08:49
理解した
08:50
各種オペレーターはObservableTypeに生えてるので
08:50
ObservableTypeなら使えるわけだ
08:50
オケオケ
Avatar
omochimetaru 06-Dec-17 08:50 AM
ああ
08:50
Convertibleはまだそれではないから結構使い勝手が違うのか
Avatar
tarunon 06-Dec-17 08:51 AM
あるメソッドを前提として色々functionが生える場合には
08:51
分ける価値があるね、そうじゃなければ特に無い
Avatar
omochimetaru 06-Dec-17 08:51 AM
なるほど。
08:52
Disposerには特にそういう芸は無いな
Avatar
omochimetaru 06-Dec-17 09:03 AM
親クラスに designated initializerが2つある場合に、 designated initializerを1つだけoverrideした時は、サブクラスでは convenience initializerは呼び出せないのに
09:03
2つ両方をoverride すると convenience initializer が使えるようになる
09:04
これはまあいいとして
09:04
2つ両方をoverrideしているが、convenience initailizerは 使えるようにならない 方法が無いのが
09:04
例のfactory initを使っている場合に限って困る。
09:05
Avatar
tarunon 06-Dec-17 09:05 AM
convenience initってoverride出来ないんだっけ
Avatar
omochimetaru 06-Dec-17 09:05 AM
privateにできそう
Avatar
tarunon 06-Dec-17 09:05 AM
factory init自体はprotocolをprivateにして隠蔽できるはず
Avatar
omochimetaru 06-Dec-17 09:05 AM
そこはそうだね
09:06
convenience init は private にして隠すことができた
Avatar
tarunon 06-Dec-17 09:06 AM
convenience init via factoryはoverrideしてunavailableしか無いんじゃあないかな
09:06
あー
09:06
convenience init自体を隠蔽するのもありですね
09:06
使わないなら
Avatar
omochimetaru 06-Dec-17 09:06 AM
というかfactory initされるから使うとぶっ壊れる
Avatar
tarunon 06-Dec-17 09:06 AM
いや
09:07
Disposableからは使いたいがサブクラス群からは使わせたくない、という話と思っていた
Avatar
omochimetaru 06-Dec-17 09:07 AM
パッケージ内部はまあいいよ危険でも
09:07
外部から触れなければ。
09:08
あとはユーザ継承だけが問題か〜 まあそのケースはスタック伸びちゃうでいいか
Avatar
tarunon 06-Dec-17 09:18 AM
ユーザーにはConvertibleだけ触らせるでいいんじゃないのとは思うけど
09:18
そうすれば一段だ
Avatar
omochimetaru 06-Dec-17 09:18 AM
だね、これはそういう意図だった > そのケースはスタック伸びちゃうでいいか (edited)
Avatar
omochimetaru 06-Dec-17 09:28 AM
b
09:29
できた〜〜〜〜
09:29
サンクス
Avatar
tarunon 06-Dec-17 09:30 AM
CompositDisposerなんとかなんないかな?w
Avatar
omochimetaru 06-Dec-17 09:31 AM
そこは多分flatMapLatestとかが重なってるのでそこに専用のinner classのDisposerを作れば
09:31
見えるようになりそう
Avatar
tarunon 06-Dec-17 09:32 AM
そこがスタック地獄になってるのは、解決出来ないか
Avatar
omochimetaru 06-Dec-17 09:32 AM
ネスト自体は本当にロジックがそうだからなくせないと思う それはそれとしてちょっと重いのでストリームの組み方は見直すつもり
Avatar
tarunon 07-Dec-17 09:38 AM
09:38
なんか見つけたんだけどこれなんだろう
Avatar
hiragram 07-Dec-17 09:39 AM
self: Selfってことはインスタンスメソッドすな
Avatar
tarunon 07-Dec-17 09:39 AM
適当にオレオレクラス作ってAnyObjectにキャストするとunrecognizedで怒られる
Avatar
hiragram 07-Dec-17 09:41 AM
09:41
_SwiftNSRangeってなんだ
Avatar
Kishikawa Katsumi 07-Dec-17 09:42 AM
名前だけ見るとNSArrayのメソッドっぽいけど。
Avatar
rintaro 07-Dec-17 09:44 AM
swift - The Swift Programming Language
Avatar
hiragram 07-Dec-17 09:45 AM
_NSArrayCore 🤔
Avatar
tarunon 07-Dec-17 09:45 AM
同じところ見てました
09:45
nextObjectはこっちかな
Avatar
rintaro 07-Dec-17 09:45 AM
_NSArrayCore ふくめ、このファイルの型は Foundation なしの stdlib で Foundation 系の型を扱うためのもの。みたいな感じだと思ってます。 (edited)
Avatar
omochimetaru 08-Dec-17 05:48 AM
関数の引数をジェネリックなプロトコルで受けると、型が決まってないからドット記法が使えない
05:49
イレイジャの型で受けるとドット記法が使えるけど性能によくない
05:49
って両方満たす作戦ない?
Avatar
tarunon 08-Dec-17 05:49 AM
普通のGenericsじゃあだめなの
Avatar
omochimetaru 08-Dec-17 05:50 AM
普通のGenerics?
05:50
func bind0<X: EventSourceProtocol>(modelStream: X) where X.Event == Model func bind1(modelStream: EventSource<Model>)
(edited)
05:51
bind1は bind1(modelStream: .of(3)) とか書ける事もあって便利
05:51
でも逆に bind1(modelStream: Property(3).asEventSource()) 変換が必要
05:52
bind0 は逆にドット記法が使えないが後者のケースでは変換が不要
Avatar
tarunon 08-Dec-17 05:52 AM
オーバーロード
Avatar
omochimetaru 08-Dec-17 05:53 AM
bind0とbind1両方定義するのって安全なんだっけ。 EventSource is EventSourceProtocol だから、曖昧なんだけど
Avatar
tarunon 08-Dec-17 05:53 AM
厳しい方にマッチするはずだからambiguousは出ない気がするね
Avatar
omochimetaru 08-Dec-17 05:53 AM
(実際には0と1はのぞいて両方共bindとしてオーバーロードの話)
05:56
やってみます
05:57
いけるっぽい。
05:58
ありがとう
05:58
これ今だとprotocolにはstatic funcが定義できないから
05:58
大丈夫だけど、それもできるばあい
05:58
EventSourceProtocol.ofEventSource.of が曖昧になりそうだ .of() だけ書いてある場合 (edited)
Avatar
tarunon 08-Dec-17 05:59 AM
いや
05:59
それでもGenerics側はProtocolが何なのかを解釈出来ないからマッチしない
05:59
一意に決まります
05:59
protocol MyProtocol { static var foo: Self { get } static var bar: Self { get } } final class MyClass: MyProtocol { static var foo: MyClass { return MyClass() } static var bar: MyClass { return MyClass() } } func func1<X: MyProtocol>(_ arg: X) {} func func1(_ arg: MyClass) {} func1(.foo)
Avatar
omochimetaru 08-Dec-17 05:59 AM
あーそういう順番なのか
Avatar
rintaro 08-Dec-17 06:01 AM
protocolにはstatic funcが定義できない
ん?
Avatar
omochimetaru 08-Dec-17 06:01 AM
@rintaro static func を持つという制約は書けるけど
Avatar
tarunon 08-Dec-17 06:01 AM
それはおもちprotocolはと解釈した
Avatar
omochimetaru 08-Dec-17 06:01 AM
プロトコル名をネームスペースとして定義するstatic funcが書けない
06:03
protocol AnimalProtocol { static func makeNya() -> Cat }
↑は Cat.makeNya() や Dog.makeNya() が呼べる事を示す定義であって、 AnimalProtocol.makeNya() という式で呼べる関数を定義するわけじゃないからいいけど
06:04
protocol をネームスペースとして protocol 宣言の内側に inner class や inner struct を定義したいって話題をたまに見かけるので
06:04
んーまあだから関数は記法がもう消費されてるからありえないけど
06:05
もしprotocolのinner classなどのネームスペース的な記述ができるようにもしなったときは、 ↑のbind0とbind1のオーバーロードに対して ドット記法があると曖昧になりそうという事
Avatar
rintaro 08-Dec-17 06:06 AM
なるほど。
Avatar
rintaro 08-Dec-17 06:20 AM
protocol AnimalProtocol {} class Cat : AnimalProtocol {} extension AnimalProtocol { static func makeNya() -> Cat { return Cat() } }
こういう話ではなくて?
06:20
ああ、AnimalProtocol.makeNya() で呼べないということですね。 (edited)
Avatar
omochimetaru 08-Dec-17 06:24 AM
はい。まあ現状の仕組みからすると呼べたら意味不明ですけど。
Avatar
rintaro 09-Dec-17 05:45 AM
https://github.com/apple/swift/pull/13342 CountableRange 廃止きましたね。 (edited)
👍 2
Avatar
omochimetaru 09-Dec-17 12:11 PM
お~~
Avatar
koher 12-Dec-17 03:04 AM
Swift で浮動小数点数使うときって Float 使いますか? Double 使いますか? Java だと double が普通だと思うんですが。
Avatar
lovee 12-Dec-17 03:04 AM
Double ですかね?そもそも指定がなかったらデフォルトで Double 使われますし…
Avatar
koher 12-Dec-17 03:05 AM
確かにデフォルトそうですね。
Avatar
omochimetaru 12-Dec-17 03:05 AM
Floatにしてた。
Avatar
koher 12-Dec-17 03:06 AM
標準ライブラリの API で、一般的な小数と取りたい部分で、 Double のみ(もしくは Float のみ)の API ってありますっけ?
Avatar
lovee 12-Dec-17 03:06 AM
いきなり意見が割れた 😇
Avatar
omochimetaru 12-Dec-17 03:07 AM
浮動小数周りの命令って32と64だと32bitのほうがパイプライン効率とかCPU上で2倍になりそう、計測はしたことないけど
Avatar
lovee 12-Dec-17 03:08 AM
Floatabs がないっぽい?
Avatar
koher 12-Dec-17 03:09 AM
03:10
1> let a: Float = -3.14 a: Float = -3.1400001 2> abs(a) $R0: Float = 3.1400001
Avatar
lovee 12-Dec-17 03:10 AM
FloatとDouble両方のページ開いて var func init( で数検索して見たけど func だけFloatが1個少なくて軽く見て見たらFloatのページにだけ abs がなかったけどドキュメント作った人のせいか
Avatar
koher 12-Dec-17 03:12 AM
CoreGraphics とかは浮動小数点数いっぱいでて来るんですが、標準ライブラリじゃないし、みんな CGFloat なんですよねぇ。
Avatar
lovee 12-Dec-17 03:13 AM
CGFloat は標準ライブラリーで使えなかったっけ?
Avatar
omochimetaru 12-Dec-17 03:13 AM
let a = 0.12 print(type(of: a)) // Double
03:13
デフォルトDoubleなのは今知った
Avatar
lovee 12-Dec-17 03:13 AM
あほんとだ使えない
Avatar
koher 12-Dec-17 03:14 AM
Java の HashMaploadFactor みたいなのないかと思ったけど、 https://docs.oracle.com/javase/jp/9/docs/api/java/util/HashMap.html#HashMap-int-float-
03:15
Swift の Dictionary にはなかった・・・。 https://developer.apple.com/documentation/swift/dictionary
Avatar
omochimetaru 12-Dec-17 03:15 AM
HashMapの負荷係数としてはDoubleは過剰とかあると思うので
03:15
用途次第だと思います
Avatar
koher 12-Dec-17 03:15 AM
Java でも float だしね。
Avatar
lovee 12-Dec-17 03:16 AM
かと言ってそもそも今の処理系はみんな64bitになってるので、32bit使っても64bit使ってもパフォーマンスに影響はないと思うんですよね…メモリは4バイト分の節約にはなりますが
Avatar
koher 12-Dec-17 03:16 AM
↓ここからして https://developer.apple.com/documentation/swift
Fundamental data types such as Int, Double, and String
だし、 Double を優先して使うのがいいのかな。
Avatar
omochimetaru 12-Dec-17 03:17 AM
32bit使っても64bit使ってもパフォーマンスに影響はないと思うんですよね
64bitマシンで32bitFloatを64bitレジスタに2個詰めていっぺんに計算したりとかできないんかな
03:18
armのSIMD命令とかもどうなんだろう
Avatar
Biacco42 12-Dec-17 03:19 AM
むしろ 64 bit アーキテクチャだと 32 bit の Float を 64 bit に変換し直すから遅いという話を聴いた気がするし、実際 iOS で Float から Double に変えたら速くなったことが
03:19
パッキングしてくれない
Avatar
lovee 12-Dec-17 03:19 AM
64bitマシンで32bitFloatを64bitレジスタに2個詰めていっぺんに計算したりとかできないんかな
多分ないんじゃないかと 🤔 それができたら char が一遍に8バイト処理できる計算になるけどそんな話聞いたことないですね(聞いたことないだけかもしれないが
Avatar
Biacco42 12-Dec-17 03:20 AM
x86_64 だとどうなんだろう…
Avatar
lovee 12-Dec-17 03:20 AM
x86_64でも今普通double使いますね
Avatar
Biacco42 12-Dec-17 03:21 AM
そうですね
Avatar
lovee 12-Dec-17 03:21 AM
少なくともC言語入門の授業では「よっぽどのことがない限りfloatよりdouble使え」と教えられますた
Avatar
koher 12-Dec-17 03:23 AM
なんで今まで Float 優先で使ってたんだろうと考えてみたけど、
03:23
昔の iOS アプリ開発が 32bit だったのと、
03:24
(おそらくそれに引きづられて)↓のような API が Float になっていることが
Avatar
omochimetaru 12-Dec-17 03:24 AM
https://developer.arm.com/technologies/neon 8x16-bit*, 4x32-bit, 2x64-bit** floating-point operations
NEON is a SIMD architecture extension for the Arm Cortex-A series and Cortex-R52 processors.
Avatar
koher 12-Dec-17 03:24 AM
関係してる気がしてきた。
Avatar
omochimetaru 12-Dec-17 03:24 AM
うーんやっぱ専用レジスタのサイズの関係でビット数が小さい方がいっぺんに処理できるベクトルの要素数が増えると思うんだけどな
03:24
一般のプログラムをコンパイラがベクトル命令に最適化するのかどうかっていう問題はあるけど (edited)
Avatar
koher 12-Dec-17 03:25 AM
UITouch の分解能ってどれくらいなんだろう? (edited)
Avatar
omochimetaru 12-Dec-17 03:26 AM
ベクトル命令自体はCoreGraphicsのMatrixとかは明示的に組み込まれてたし。 (edited)
Avatar
koher 12-Dec-17 03:26 AM
UITouch の分解能が低いなら Float でも合理的か。
03:26
でも Swift だと型変換するの面倒かも?
03:28
gccだと-marchでSIMD(Neon)狙ってくれ みたいなオプションあったりする
Avatar
koher 12-Dec-17 03:29 AM
@omochimetaru CoreGraphics は CGFloat だから、 64bit 環境では 64bit 浮動小数点数になってると思う。
Avatar
omochimetaru 12-Dec-17 03:30 AM
@koher あ、CoreGraphicsじゃなくて、GLKitのGLKMatrix4x4だ
Avatar
koher 12-Dec-17 03:30 AM
GL は特殊ケースじゃない? (edited)
03:32
頂点配列とかも、演算速度優先で Float とか普通かと。
Avatar
omochimetaru 12-Dec-17 03:35 AM
GLK_INLINE GLKMatrix4 GLKMatrix4Add(GLKMatrix4 matrixLeft, GLKMatrix4 matrixRight) { #if defined(__ARM_NEON__) float32x4x4_t iMatrixLeft = *(float32x4x4_t *)&matrixLeft; float32x4x4_t iMatrixRight = *(float32x4x4_t *)&matrixRight; float32x4x4_t m; m.val[0] = vaddq_f32(iMatrixLeft.val[0], iMatrixRight.val[0]); m.val[1] = vaddq_f32(iMatrixLeft.val[1], iMatrixRight.val[1]); m.val[2] = vaddq_f32(iMatrixLeft.val[2], iMatrixRight.val[2]); m.val[3] = vaddq_f32(iMatrixLeft.val[3], iMatrixRight.val[3]); return *(GLKMatrix4 *)&m;
03:36
GLKitの場合はシェーダーに飛ばした後の精度がどうせ32bitしか無いっていう別の理由もあると思うけど、 それはそれとして、CPU側で行列演算する必要もあるので、専用命令を使った場合に32bitのほうが早いっていうのも理由に含まれていると思う
03:37
ベクトル命令じゃなくて普通の単体の命令の場合は32bitから64bitへの昇格/降格が挟まって遅くなるってこともありえると思うけど
03:37
一方で(現在のSwiftコンパイラ/LLVMバックエンドがサポートしてるかは別として) GCCとかで通常のコードからなるべくベクトル命令を吐くっていうコンパイラ最適化は実在する技術だから
03:38
それを見据えて期待してFloatにしておくと良いのでは、ってのが考えです
03:38
頂点配列とか要素数が多くなってきた場合にはキャッシュサイズの影響が大きくなってきそうという別のメリットもあるけど、今の議題はなんかそういう場合では無さそう
Avatar
koher 12-Dec-17 03:39 AM
今知りたいのは、一般的に FloatDouble のどちらが使われてるのかということですね。
03:40
もちろん、適材適所はあるけど、もっとざっくりと、小数を作りたいと思ったときに Swift ではどちらを使うのが一般的なのかと。
Avatar
lovee 12-Dec-17 03:41 AM
暗黙的な処理としては let a = 0.12 の場合 aDouble なので Double の方が一般的かと思いますね 🤔
Avatar
koher 12-Dec-17 03:42 AM
そんな気がしてきました。自分がなんで Float 使ってたのかを考えると、昔の iOS アプリ開発から惰性でそうしてるだけな気がしてきました。 (edited)
Avatar
tarunon 12-Dec-17 04:20 AM
public struct CGFloat { /// The native type used to store the CGFloat, which is Float on /// 32-bit architectures and Double on 64-bit architectures. public typealias NativeType = Double
これ好き
04:21
CGFloatおまえFloatちゃうやんけ!っていう
Avatar
lovee 12-Dec-17 04:35 AM
型としての Float ではなく字面の意味通りのFloatだから(震え声
Avatar
t.ae 12-Dec-17 04:36 AM
public typealias Float64 = Doubleなのでセーフ
Avatar
koher 12-Dec-17 04:36 AM
FloatDouble って名前に統一感ないですよね。せめて SingleDouble にするか、 Float32Float64 にするかしてほしい。 Swift が悪いわけじゃないけど。
Avatar
lovee 12-Dec-17 04:37 AM
Float80あるしFloat64でいいと思うんですよね
Avatar
lovee 12-Dec-17 04:37 AM
IntだってInt64あるし
Avatar
koher 12-Dec-17 04:37 AM
個人的には、 Float32Float64 作って、 Int みたいな位置の Float ほしい。
Avatar
omochimetaru 12-Dec-17 04:37 AM
ObjectPascalならSingleだよ
Avatar
t.ae 12-Dec-17 04:39 AM
Int みたいな位置の Float ほしい。
BLASとか使うのめちゃくちゃめんどくさくなりそう
Avatar
lovee 12-Dec-17 04:41 AM
型名にも技術的負債が…
Avatar
koher 12-Dec-17 04:41 AM
typealias あったのか・・・
04:45
@t.ae それはそうだけど、そこは仕方ない気も。
Avatar
t.ae 12-Dec-17 04:48 AM
今もUnsafe*Pointer<Int32>受ける関数とかありますけどね。 そもそもIntのサイズがネイティブに依存するメリットがいまいち分かっていないです。
Avatar
koher 12-Dec-17 04:49 AM
一般的なコードで整数を扱いたいときにそれが Int32 だろうが Int64 だろうが成り立つことがほとんどで、
04:50
32 bit 環境と 64 bit 環境でコードを共通化できないのは辛くない?
Avatar
omochimetaru 12-Dec-17 04:50 AM
僕もInt固定が良い派
04:50
Int32って書いとけば共通化はできますよ
04:50
むしろマシンによって挙動が変わりうるのが怖い
04:51
掛け算のオーバーフローとか桁数半分の2乗でいくので稀に怖いです
04:51
ふだんは64で作ってて32環境だけでエンバグする怖さですね
Avatar
koher 12-Dec-17 04:52 AM
Int って書いてるときはオーバーフローは Logic failure だし、バイト数で壊れるようなコードはそもそも Int で書いちゃいけないかと。 (edited)
04:53
単純に現実的な範囲で N までをサポートする型として使って、その N が環境によって異なるだけ。
Avatar
omochimetaru 12-Dec-17 04:53 AM
壊れると思ってるときは書かないからよくて、
04:53
うっかり使ってしまうリスクですね
04:54
エンバグ条件もかなりレアになるから潜伏しやすい
Avatar
koher 12-Dec-17 04:54 AM
Int32 って書いたコードは未来に Int128 が当たり前になった世界でも Int32 のままになっちゃうよ。
Avatar
lovee 12-Dec-17 04:54 AM
自分もそういうシビアな「絶対この桁数じゃないとダメ」のようなシチュエーション比較的にそんなに一般的ではない気がするので、そのような場合に Int64 とか Int32 使って、普通の環境は Int でよしなりにプラットフォームに合わせて使わせてくれる方が嬉しいかな派ですね
Avatar
omochimetaru 12-Dec-17 04:54 AM
なるべくどこでも同じ動きの方がよくないですか?なんでも
Avatar
lovee 12-Dec-17 04:54 AM
テーブルのセル数とか Int32 でも Int64 でも変わらないでしょう派()
Avatar
koher 12-Dec-17 04:55 AM
テストのときに Int が色々なビット数で動いてくれるとうれしいとは思う。
Avatar
lovee 12-Dec-17 04:55 AM
むしろテーブルのセル数が Int32 で足りないシチュエーションって相当レアですよね…
Avatar
omochimetaru 12-Dec-17 04:56 AM
そういう値は128ビットの時代になったからといって32のままで大丈夫ですね
Avatar
koher 12-Dec-17 04:56 AM
Java とか int が 32 bit 固定だけど、今の 64 bit 当たり前の時代でも 32 bit に縛られちゃってるのでは?
Avatar
omochimetaru 12-Dec-17 04:56 AM
マシンの進化に合わせて大きくなるのが嬉しいって場面があまり思い当たらない
Avatar
koher 12-Dec-17 04:57 AM
04:58
今さら標準ライブラリのほとんどの箇所で intlong にするとか無理では。
04:58
しかも、過去に書かれたコードが「整数」を使いたいのか「32ビット整数」を使いたいのか区別されてないから (edited)
04:59
コンバートしようとしてもできない。「32ビット整数」のつもりの箇所はぶっ壊れる。
04:59
つまり、永久に32ビット整数を使い続けるか、古いコードをすべて捨てて新しい世界に行くかしかない。
Avatar
omochimetaru 12-Dec-17 05:01 AM
配列の要素数に関してはcppのstd::size_tが筋が良いとは思います
05:02
これはポインタで表せる空間サイズに対応した型で
05:02
たとえ128ビットのintのマシンでも
05:02
メモリアドレスが64ビットなら、
05:02
128ビットのインデックスに意味がないからです
05:03
SwiftのIntも、ネイティブのポインタサイズの整数として
05:03
定義されているんで、配列についてはそれで良いかも
Avatar
Kishikawa Katsumi 12-Dec-17 05:03 AM
古いコードをすべて捨てて新しい世界に行くかしかない。
Avatar
omochimetaru 12-Dec-17 05:03 AM
アーキテクチャによってはポインタサイズとIntサイズを区別することもあって
Avatar
Kishikawa Katsumi 12-Dec-17 05:03 AM
新しい世界は数年ごとに来るからそれで良いかも
Avatar
omochimetaru 12-Dec-17 05:04 AM
それはまた話がかわりそう
Avatar
Kishikawa Katsumi 12-Dec-17 05:04 AM
数年前は64ビットサイズのIntとかなかった。
Avatar
koher 12-Dec-17 05:05 AM
@omochimetaru List を出したのは例であって、一般的に整数の意味合いで使われてる int がずっと 32 bit のままが辛いということです。
05:05
@Kishikawa Katsumi うーん、でも Java はもう int が 32 ビットのまま変わらず 20 年使われてますよ。
Avatar
omochimetaru 12-Dec-17 05:05 AM
「一般的な整数」っていうのがあるのかなあと思います 純粋な整数計算アルゴリズムとかはそういうのいると思うけど、それはむしろ無限精度整数の方が良いと思うし。
05:06
ちゃんとつきつめていけば、人間がUIで見通せる要素数、とか、メモリサイズに関連づけされた数、とか
05:06
サイズ要件がだいたいはちゃんとあると思うんですよ
Avatar
Kishikawa Katsumi 12-Dec-17 05:07 AM
^ Javaがそういう選択をしたというのはそれはそれで私は尊重したいと思います。ただいずれ32は無くなって、64or何かみたいなことは起こるので、そのときにより良い選択ができるようにこういう議論はしておいたらいいのかと思いますね 😃 (edited)
Avatar
koher 12-Dec-17 05:09 AM
@omochimetaru それで UITableView のセルの数&インデックスは Int32 だけど Array の要素数&インデックスは Int64 で境界で全部明示的変換が必要ですとか辛くないですか?
05:11
あと、↑のポインタサイズの話は ArrayList 的なものを想定してると思うけど、 LinkedList とかを考えると話が変わってくるのでは? List は一般的なインタフェースだし。
Avatar
omochimetaru 12-Dec-17 05:11 AM
1要素が1バイトはあるので
05:11
ポインタ表現幅を超えることはないのでは
05:11
あ、ファイルストレージとかと連動するならありえますね それはもう別の型が良さそうだけど。
05:12
うーん、Int32とInt64の都度変換ですが、cppで厳密にやるとそうなるんですけど、
Avatar
koher 12-Dec-17 05:12 AM
イミュータブルな List が動的に要素を計算するとかあり得るのでは?( List のアップデート系のメソッドはオプションのはず)
Avatar
omochimetaru 12-Dec-17 05:12 AM
僕は個別にToInt全部包むようにして
05:12
そこで溢れチェックささるようにしたら
05:13
安心感あって良かったですよ
Avatar
koher 12-Dec-17 05:13 AM
それって何も考えずに境界でキャストしまくるだけになって結局壊れないかなぁ。
Avatar
omochimetaru 12-Dec-17 05:15 AM
このばあいだとサイズの最大値が理由ともに片付けされているので
05:15
クラッシュするときっていうのはなんらかの問題でその要素数などの仮定がぶっこわれたということなので
05:15
そのキャストのところで落ちる方が
05:16
問題の検出がはやくなっていて良いと思う
Avatar
koher 12-Dec-17 05:16 AM
@Kishikawa Katsumi Java やってた頃は固定されてる安心感があったんですが、いざ 64 bit への移行の世界を経験して、これからどうするんだろう?と思いますね〜🤔 最近の Java 事情詳しくないですが。
05:17
@omochimetaru 脳内で一般的整数として扱ってるもの同士でやりとりするためにいちいちキャストが必要というのはちょっと許容しかねる気が。
05:19
@omochimetaru バイト列として扱ったりするときは当然 Int から Int32 とかに変換するわけで、その境界で気付くんじゃないかな?普段は Int として扱っていて、ビット数を気にする処理をする際に IntXX に変換で十分だと思うけどなぁ。
Avatar
omochimetaru 12-Dec-17 05:19 AM
いや、前提が逆ですね、「一般的整数」として脳内の認識が緩まってしまうことで、
Avatar
Kishikawa Katsumi 12-Dec-17 05:19 AM
私も詳しくはなくて互換性を重視したか、急な変化を避けたんだと思うんですけど、Swiftもいずれそういう選択は来るんだろうなと。今は標準APIを全部変える選択はまあ無いけど、その時にはありかも。
Avatar
omochimetaru 12-Dec-17 05:19 AM
64bitでは動くが32bitではおかしくなる、というバグを生みうることを懸念しているので
05:19
それは脳内の認識が最初からゆるいのでちゃんと決めたほうがいいってアイデアです
05:21
バイナリ操作の話はまた別かなと思います 64bitの時代になったからといってIntに42億を超える値を入れるシチュエーションそうそう無いはずで、 むしろなんらかのバグで計算が狂って入っちゃった(でも64bitだから動いてしまう)っていう事の方が多そう
05:22
ちなみに新しい言語だとRustが具体的サイズ主義ですね (edited)
Avatar
koher 12-Dec-17 05:22 AM
うーん、整数という概念で用いているものに対して、これは Int32 とか Int64 とか色分けするのは変だと思うし、それが 32 ビット(に限らない XX ビット)に取り残される原因を生むと思う。
05:25
Intに42億を超える値を入れるシチュエーションそうそう無い
そうそうないだけであり得て、 Facebook がユーザー 21 億超えたら(古の 32 ビットに引きずられて)それまでのコードが動かなくなりましたとか辛い気が。
Avatar
omochimetaru 12-Dec-17 05:26 AM
世界人口が2^32超えてるからユーザーIDはInt64がいいんじゃないですかね
05:26
それこそ雑に Int をいつもつかう文化だったからやってしまう間違いな気がする
Avatar
koher 12-Dec-17 05:26 AM
でも Java のコレクションの sizeint なんです。
Avatar
omochimetaru 12-Dec-17 05:26 AM
いつも32と64気にしてればそこで回避できないか
Avatar
koher 12-Dec-17 05:27 AM
そして、それは Java が作られたときにはリーズナブルだったわけで
Avatar
omochimetaru 12-Dec-17 05:28 AM
コレクションのサイズはポインタサイズが良いと思いますよ
05:28
Javaより先にC++がそうしていたので
05:28
昔だったから思いつけなかったって話ではないはず
Avatar
koher 12-Dec-17 05:28 AM
いや、なのでコレクションのサイズは一例であって
Avatar
omochimetaru 12-Dec-17 05:28 AM
Javaには「ポインタサイズ」の概念が無いから
05:28
マシンのメモリサイズを見据えた物の考え方がないのかと
Avatar
koher 12-Dec-17 05:29 AM
ありとあらゆる整数サイズが 32 ビットに固定されてるのが Java の世界で
Avatar
omochimetaru 12-Dec-17 05:29 AM
個別の間違いは個別の間違いだから
05:29
都度都度なおしていきましょうで良いと思う
05:29
フワッとしておけば後々伸ばせる、みたいな考え方は混乱をウムと思います
Avatar
koher 12-Dec-17 05:30 AM
Java の標準ライブラリの int を全部 long にしましょうとか無茶でしょ?
Avatar
omochimetaru 12-Dec-17 05:30 AM
そうかな
05:30
Swiftだったら
05:30
その程度の破壊的変更はやってますよ (edited)
05:30
Javaの人たちはそういう点で保守的というだけで・・・
Avatar
koher 12-Dec-17 05:30 AM
Swift はまだ実用の範囲が狭いからね。
05:30
それをやってるから本格的に採用できないということもある。
Avatar
tarunon 12-Dec-17 05:30 AM
逆説的に言うとその手の破壊的変更がある限りSSSは普及しない
Avatar
koher 12-Dec-17 05:32 AM
Java 1X からは int を 64 ビットにします(もしくは int で書かれてた API の大部分を long にします)とかやったら世界崩壊しそうな気が。 (edited)
Avatar
omochimetaru 12-Dec-17 05:32 AM
うーむ・・・ Java.util.とは別に java10.util.ArrayList とか用意して移行していくのはどうですかねえ
05:32
SwiftのSSSも同じで。
05:33
時代に合わせて新しい標準ライブラリを作る、古い実装を動かしたい人はそのまま動かす、
05:33
時代に合わせてパフォーマンスやスケールを伸ばしたい人は書き換える。
Avatar
Kishikawa Katsumi 12-Dec-17 05:34 AM
私はそういう大きな移行を促進するのはある程度パワープレイが必要だと思いますね。それか明確なメリットがあるか。
Avatar
koher 12-Dec-17 05:36 AM
Date を新しい API にするだけでも大変そうだったのに https://qiita.com/tag1216/items/91a471b33f383981bfaa java.util をまるっと置き換えますとか地獄絵図な気が。
Javaで日付/時間を扱うには従来はDate/Calendar/DateFormat等のクラスを使っていたが(以下、旧API)、Java8からはjava.timeパッケージに新しくAPIが追加された(以下、新API)。 しかし新AP...
Avatar
omochimetaru 12-Dec-17 05:37 AM
えっと、ライブラリの移行は仮定の話しで、 僕の意見としては、Int32, Int64, IntPtr に関してはその3つをちゃんと考えて決めておけば、そもそも将来的に移行したくならないと思う、です。
Avatar
koher 12-Dec-17 05:38 AM
パフォーマンスの問題もないかな? 64 ビットに変換してから計算されたりしない?
Avatar
omochimetaru 12-Dec-17 05:40 AM
浮動小数と違ってその昇格が実質クロック遅延無しでできそう
05:41
ビット線を併合してゼロ埋めするだけだから
05:42
うーんでもそれは浮動小数も一緒か・・・? そこは知らないです (edited)
05:43
ただ回路的には小さいから、仮に昇格コストがでかいとしたら、32bit演算機も搭載しておけばいいんじゃないかって気はしますけど
Avatar
koher 12-Dec-17 05:43 AM
将来的に移行したくならない
これがそうじゃない気がして、想定できないだけでそういうケースがぽこぽこ出て来ると思う。
Avatar
omochimetaru 12-Dec-17 05:43 AM
まあ、それ自体はIntに限った話しじゃなくて
05:44
Unicode絵文字みたいに世界の事情が変わっちゃって、とかはままありますね
Avatar
koher 12-Dec-17 05:44 AM
Int はプリミティブすぎて影響範囲が他よりめちゃくちゃ大きいんじゃないかなぁ。
Avatar
omochimetaru 12-Dec-17 05:46 AM
それが無いと思うんですよね、実際に 2^32より大きい値をIntに自然に入れるのをみたことがないから。 明示的にInt64な有理数(分母と分子のタプル)時刻型とか、さっきの大規模サービスのIDとか、事前に想定されたシチュエーションぐらいです。
Avatar
koher 12-Dec-17 05:46 AM
大きなお金とか
Avatar
omochimetaru 12-Dec-17 05:46 AM
「普通の整数」としてIntが使われていて、64bit環境において、そこに42億以上の値を入れた
05:46
って場面を見たことがないと思います
Avatar
koher 12-Dec-17 05:46 AM
ディスク容量とか
Avatar
omochimetaru 12-Dec-17 05:46 AM
お金も普通お金型使いますよ
05:46
少数桁の税率計算とかでいろいろと面倒があるので
Avatar
hiragram 12-Dec-17 05:47 AM
普通お金型つかいますよが全然できてないJava屋さんはいっぱいいそう
Avatar
omochimetaru 12-Dec-17 05:47 AM
いや、さすがに居ないと思う・・・
05:47
Java屋さんお金型使うプロでしょ・・・
Avatar
koher 12-Dec-17 05:48 AM
お金の例はルールと密接に絡んでるから特殊だったとしても
Avatar
omochimetaru 12-Dec-17 05:48 AM
ディスク容量は確かに難しいですね
05:48
予想を超える爆発的増加がありえそう。
Avatar
koher 12-Dec-17 05:49 AM
32 bit の世界では仕方なく諦めて long を使ってたものが、 64 bit の世界では普通にとりあえ使えるようになってるのに、古い仕様にひきずられて永久に面倒な取り扱いを強要されるの辛そう。 (edited)
Avatar
omochimetaru 12-Dec-17 05:50 AM
実際 fseek はそんな事になってますね
05:51
long なんだけど long が32bitの環境があるので64bit用のオーバーロードがOSによってはオリジナルで提供されている
05:51
ただこれはこれで逆に示唆的で、 long っていう抽象的な型だったのに
05:51
互換性のために32bit固定されちゃって
05:51
longの柔軟性が将来的に発動できなかったんですけど・・・ (edited)
Avatar
koher 12-Dec-17 05:51 AM
あ、↑の long は Java の64 bit 整数の意図ね。
05:52
互換性のために32bit固定されちゃって
うーん、これは将来的に起こらないように Swift では注意深く進めていくしかないんだろうけど
05:52
今の Swift なら簡単だけど、広く使われてたら難しいかもしれないなぁ。
Avatar
omochimetaru 12-Dec-17 05:53 AM
ちなみに今の例にでてきたlongが32なのはバイナリ互換おばけのwindowsさんです
05:54
同じような話しが C++ の char型にもあって、 charは「1バイト以上」って定義だったんですけど、 みんなが1バイトと仮定したコードを書きすぎて駄目になった
05:54
それで近年になって char8_t を明示的に追加しようぜって話がでてきた。
05:55
現実的な課題としてはそっちの方向のほうが難しい気がしてきました
Avatar
koher 12-Dec-17 05:55 AM
それはバイト型がなかったのが問題で、別の話な気がする。
Avatar
omochimetaru 12-Dec-17 05:55 AM
wchar_t は 2バイト以上」っていうのも同じ問題をおこしましたよ
05:56
2011年に改正された C/C++ の標準規格、C11 と C++11 では、新たに2つの文字型が導入された。char16_t と char32_t であり、それぞれ UTF-16 と UTF-32 を内部表現とする。
05:56
結局こうなりました・・・
05:56
まあ文字は整数より意味が強いから問題としては別かも。
05:57
SwiftのIntはポインタサイズ型だから128ビット時代にもいける気もしますね
05:58
JavaのJNIコードは128ビット時代になったら long でポインタをハードキャストしてるところをまた直さないといけないのか・・・
Avatar
koher 12-Dec-17 05:58 AM
C/C++ の場合は長らく固定サイズの型が標準で提供されてなかったのが問題なのでは?
05:59
Swift みたいに IntXXInt でキレイに分かれてたらそんなにひどいことにはならない気が。
Avatar
omochimetaru 12-Dec-17 05:59 AM
固定したい要求のある場面で明示的にそれが記述できないからか
05:59
たしかにSwiftでバイトサイズが絡む時は UInt8 とか出てきますね。
Avatar
koher 12-Dec-17 06:00 AM
なので、固定しなくてもいい(一般的な整数を想定してる)ケースは Int 、固定したいケースは IntXX でうまくいくと思うんだけどなぁ。
Avatar
Kishikawa Katsumi 12-Dec-17 06:05 AM
私は基本的にサイズを固定すべきで「一般的な整数」というのが必要なケースの方が例外的だと思ってるんですけど、 @koher さんは逆ですか?
Avatar
koher 12-Dec-17 06:13 AM
@Kishikawa Katsumi はい、僕は概念として一般的な整数があると思っていて、特殊なケースでそれを固定サイズの整数として扱いたいんだと思っています。
06:13
たとえば、 UITableView のセル数は概念として一般的な整数だと思うんですよね。ユースケースを考えたら 99% のケースではそれが Int32 に収まるとしても。 (edited)
👍 1
Avatar
Kishikawa Katsumi 12-Dec-17 06:21 AM
私はそういうのは一般的な整数ではなくてハード・ソフトの制約を考えてInt32かInt64などに厳密にモデリングするべきと思うんですよね。
Avatar
koher 12-Dec-17 06:27 AM
うーん、そのあたりは好みというか宗教になってしまいそうですねぇ。。。
06:29
多分、型はコンピュータの内部表現を写し取っているべきだとすると Int32 になって、概念を写し取っているべきだとすると Int になるんじゃないでしょうか。
Avatar
Kishikawa Katsumi 12-Dec-17 06:42 AM
私もそんな気はしている&koherさんの意見にもある程度納得しているんですけど、例えば文字列も「一般的な文字列」というのは厳密にはないのであってプログラミングするにはどこかで曖昧さをなくす必要があって、で、それはコンピュータの内部表現に依存するので、そうするとIntっていうのはほとんどのケースには便利だけど、、、という感じですね。
Avatar
koher 12-Dec-17 07:03 AM
文字列についても Swift ではできるだけ Unicode を隠蔽して書記素クラスタで「一般的な文字列」に近づけているとは思いますが、所詮文字列は人工的なものなのに対して、整数はより根源的な存在だから余計に Int32 等にすることに(僕が)違和感を感じるのかもしれません。
Avatar
koher 12-Dec-17 07:44 AM
-------------- ↓これできないのバグでしょうか? FooProtocolFoofoo の実装をコメントアウトすれば動きます。少なくともエラーメッセージはおかしいと思います。
protocol FooProtocol { func foo(_ f: (inout Int) -> ()) } extension FooProtocol { func foo(_ f: (inout Int) -> ()) { var x = 0 f(&x) print(x) } } struct Foo : FooProtocol { func foo(_ f: (inout Int) -> ()) { var x = 42 f(&x) print(x) } } let a = Foo() a.foo { $0 += 1 }
inout-hof.swift:22:9: error: passing value of type 'Int' to an inout parameter requires explicit '&' a.foo { $0 += 1 } ^ &
(edited)
Avatar
rintaro 12-Dec-17 07:59 AM
バグっぽいですね。最後の行 a.foo { $0 += 1; () } でも動きます。
Avatar
koher 12-Dec-17 07:59 AM
; () 足して動くのヤバイですね。
Avatar
omochimetaru 12-Dec-17 08:00 AM
不思議なバグだ
Avatar
rintaro 12-Dec-17 08:01 AM
single expression クロージャの型推定が出来なくて(バグ1)、その理由を探すロジックが変な診断(バグ2)。って感じかと。 (edited)
Avatar
koher 12-Dec-17 08:02 AM
類似の探してみてなければ報告しておきます。
👍 1
Avatar
rintaro 12-Dec-17 08:06 AM
あ、 master だと動くみたいです。 4.1も試してみよう。
Avatar
koher 12-Dec-17 08:07 AM
なるほど。じゃあ報告は不要ですね。
Avatar
rintaro 12-Dec-17 08:09 AM
4.1でも動きました。
Avatar
koher 12-Dec-17 08:09 AM
おお。
Avatar
omochimetaru 13-Dec-17 02:37 AM
Still experimental. Work to eliminate ArraySlice in favor of Slice + conditional conformance. Requires additional features that would need evolution proposals: new ContiguouslyStored protocol that...
02:37
ArraySliceを削除してSliceを作って
public typealias ArraySlice<T> = Slice<[T]>
にするPR
(edited)
Avatar
koher 13-Dec-17 02:47 AM
えーー
02:48
これって Proposal あったっけ?
Avatar
omochimetaru 13-Dec-17 02:48 AM
APIは変わらないんじゃないですか?typealiasだし
Avatar
tarunon 13-Dec-17 02:48 AM
Proposal出す時にPR参照は割とある気がする
Avatar
omochimetaru 13-Dec-17 02:48 AM
ProposalもMLも見てないけど、できてからメール出すパターンも多い
Avatar
koher 13-Dec-17 02:48 AM
でも Slice を導入するのは大きな変更では?
Avatar
t.ae 13-Dec-17 02:49 AM
Sliceはいまもあるのでは?
Avatar
omochimetaru 13-Dec-17 02:49 AM
あ〜そっちはたしかに。
02:49
え、あるの
Avatar
t.ae 13-Dec-17 02:49 AM
なんかいま補完ででてましたけど
Avatar
omochimetaru 13-Dec-17 02:49 AM
www
Avatar
koher 13-Dec-17 02:49 AM
↓もなるの?
typealias Substring = Slice<String>
(edited)
Avatar
omochimetaru 13-Dec-17 02:49 AM
わからんです。
02:50
プルリクの見出しとか見る限りStringの話はされてないですね。
02:50
なんだこれ・・・こんなんあったんか・・・・
Avatar
koher 13-Dec-17 02:51 AM
えーー、 EasyImagy の ImageSlice の名前どうしよ。できるだけ ArraySlice を踏襲するようにしてたのに。
Avatar
omochimetaru 13-Dec-17 02:51 AM
ていうかSee Alsoのところに
02:51
なんちゃらSliceがめちゃめちゃあるな
Avatar
t.ae 13-Dec-17 02:51 AM
@koher それもSliceを使った実装にできるのでは?
02:51
二次元はきついのかな?
Avatar
omochimetaru 13-Dec-17 02:51 AM
次元が全然違うから無理そう
Avatar
koher 13-Dec-17 02:51 AM
せっかく ImageProtocol を導入して ImageImageSlice で共通の実装を持たせるとこが今朝大分できたのに・・・。
02:52
2 次元は Slice にできないと思う。
02:52
まあ、 ArraySlice の名前が残るならそれでもいいけど、
02:53
Subimage にするか ImageSlice にするかで迷って、 ArraySlice 的なアップデートができるからそっちに寄せて ImageSlice にした。
02:55
ArraySlice おもしろくて、↓みたいな挙動する。
let a = [2, 3, 5, 7, 11] let b: ArraySlice<Int> = a[1...3] // [3, 5, 7] let c: ArraySlice<Int> = [3, 5, 7] b[1] // 3 c[0] // 3 b == c // true
Avatar
omochimetaru 13-Dec-17 02:56 AM
9> b[b.startIndex..<b.endIndex] $R2: ArraySlice<Int> = 3 values { [1] = 3 [2] = 5 [3] = 7 } 10> c[c.startIndex..<c.endIndex] $R3: ArraySlice<Int> = 3 values { [0] = 3 [1] = 5 [2] = 7 }
02:56
これ一度は絶対踏みそうなんだよなあ
02:57
専用の型にして生のIntは渡せないほうが良いような気がするけどArrayと透過的な取扱にしたいというのもあるしなあ
Avatar
koher 13-Dec-17 02:59 AM
これを踏襲して、↓みたいな挙動にしてる。
let a = Image<Int>(width: 4, height: 3, pixels: [ 0, 0, 0, 0, 0, 8, 9, 0, 0, 0, 0, 0, ]) let b: ImageSlice<Int> = image[1...2, 1...1] // [[8, 9]] let c = ImageSlice<Int>(width: 2, height: 1, pixels: [8, 9]) b[1, 1] // 8 c[0, 0] // 8 b == c // true
(edited)
Avatar
ukitaka 13-Dec-17 04:20 AM
https://github.com/apple/swift/blob/master/docs/StringManifesto.md#different-type-shared-storage このへんの話と合わせて Slice<T> is T みたいなサブタイピングが追加されそうな予感
swift - The Swift Programming Language
Avatar
omochimetaru 13-Dec-17 04:22 AM
SubstringからStringとかに戻すタイミングで
04:22
部分バッファのコピーが発生するのを
04:22
コントロールできなくなっちゃうからそれはないんじゃないでしょうか
Avatar
koher 13-Dec-17 04:26 AM
@omochimetaru
The downside of having two types is the inconvenience of sometimes having a Substring when you need a String, and vice-versa. It is likely this would be a significantly bigger problem than with Array and ArraySlice, as slicing of String is such a common operation. It is especially relevant to existing code that assumes String is the currency type -- that is, the default string type used for everyday exchange between APIs. To ease the pain of type mismatches, Substring should be a subtype of String in the same way that Int is a subtype of Optional<Int>. This would give users an implicit conversion from Substring to String, as well as the usual implicit conversions such as [Substring] to [String] that other subtype relationships receive.
Avatar
omochimetaru 13-Dec-17 04:28 AM
ふむふむ
Avatar
koher 13-Dec-17 04:28 AM
Optional だけでなくさらなる黒魔術を導入しようとしてるのか?😇
Avatar
tarunon 13-Dec-17 04:35 AM
まずい
Avatar
koher 13-Dec-17 05:31 AM
↑に書いたコード、 iOS から見るとシンタックスハイライトされてない・・・。なぜ?パースのしかたが違うのかな?
Avatar
koher 13-Dec-17 05:39 AM
Substring is a String 無理だと思うんだけどな。
05:39
let s = "abc" let t: Substring = s[s.index(s.startIndex, offsetBy: 1)...] // "bc" let i = t.startIndex print(t[i]) // "b" let u = String(t) print(u[i]) // "c"
05:40
↑だからサブタイプとしての要件を満たせない気が。
Avatar
omochimetaru 13-Dec-17 05:40 AM
関数の引数に渡すときとかに String(substr) を暗黙に呼び出すとか
05:40
そういう意味かなと↑の文を読んで思ったけど
Avatar
koher 13-Dec-17 05:41 AM
実際はそうだけど、それはサブタイプではない。
Avatar
omochimetaru 13-Dec-17 05:41 AM
はい
05:41
だからそこらへんは厳密な議論をしてないとおもった
Avatar
koher 13-Dec-17 05:42 AM
Optional はもう一歩踏み込んでいて、↓ができる。
class A { func foo() -> Int? { return nil } } class B : A { override func foo() -> Int { return 42 } }
05:43
StringSubstring は今はできない。
05:44
ただ、実際のところ IntInt? のサブタイプにはなってなくて、↓はエラー。
9> let a: Int? = 42 a: Int? = 42 10> a.map { $0 * 2 } $R0: Int? = 84 11> let b: Int = 42 b: Int = 42 12> b.map { $0 * 2 } error: repl.swift:12:1: error: value of type 'Int' has no member 'map' b.map { $0 * 2 } ^ ~~~
👀 1
Avatar
rintaro 13-Dec-17 05:45 AM
引数としては Array<T> を UnsafePointer<T> に渡せるなどの黒魔術があるので、サブタイプというよりは、引数マジックならいい気はします。
05:45
StringUnsafePointer<UInt8> に渡せるし。
Avatar
omochimetaru 13-Dec-17 05:45 AM
完全に今思いついたんですけど
05:46
その手の引数マジックも明示的な方がいい気がする
05:46
例えば1文字だけ記号つけるとか
05:46
そういう文法で。
Avatar
koher 13-Dec-17 05:46 AM
↓は単なる代入時の暗黙の変換よりも踏み込んだことを意図しているのかと思ったけど、そうじゃないのかな?
Substring should be a subtype of String in the same way that Int is a subtype of Optional<Int>.
05:47
ただ、暗黙の型変換にしても反対ですが。
Avatar
omochimetaru 13-Dec-17 05:47 AM
let str: String = "hello" strlen(str) // これはだめにして strlen(^str) // こうするみたいな。
(edited)
Avatar
tarunon 13-Dec-17 05:47 AM
optionalもその範疇で、wrapping operatorがあるといいなと思っていて
Avatar
koher 13-Dec-17 05:48 AM
@omochimetaru UnsafePointer 周りは & がその役割してるのでは?
Avatar
tarunon 13-Dec-17 05:48 AM
暗黙的に型変換するものを全部その体で扱うのなら、それ用のオペレーターがありOptionalもそこに類するのがよい
Avatar
omochimetaru 13-Dec-17 05:48 AM
@koher ArrayとStringのCポインタ変換は&いらないですよ
Avatar
tarunon 13-Dec-17 05:48 AM
^とか~がいいなぁと思った
Avatar
omochimetaru 13-Dec-17 05:48 AM
&はinoutとの対応メタファーになってて、MutablePointerに変換する時はつけるけど。
Avatar
rintaro 13-Dec-17 05:50 AM
in the same way that Int is a subtype of Optional<Int>. はもっと強い意味だけど、
the default string type used for everyday exchange between APIs.
を解決するのにサブタイプは必要ないんじゃないか?っていう意見です。
Avatar
koher 13-Dec-17 05:53 AM
@omochimetaru そうだった。
05:53
& も構文失敗してる気がする。↓ややこしい。
func f(_ p: UnsafePointer<Int>) { print(p[0]) } func g(_ p: UnsafePointer<[Int]>) { print(p[0].count) } var a = 42 var b = [2, 3, 5] f(&a) f(&b) g(&b)
05:54
f(&b) が良くない
05:55
@rintaro > 解決するのにサブタイプは必要ないんじゃないか? それはそうですね。ただ、明示的に型変換するくらいがちょうどいいと思うんですけどねぇ。
05:56
どうしても型変換しまくるコード書くときは(パーサとか)
Avatar
omochimetaru 13-Dec-17 05:56 AM
Substringを受けるオーバーロードをその場で足す (edited)
Avatar
rintaro 13-Dec-17 05:56 AM
型変換して渡すときに明示オペレータ必須のほうが良いというのは同意です。
Avatar
koher 13-Dec-17 05:56 AM
internal な後置演算子作って変換すればいいし
05:57
(前置でもいいけど後置の方が好み)
06:01
@omochimetaru ^ で変換、今もできる。
prefix operator ^ prefix func ^(value: Substring) -> String { return String(value) } let s = "abc" let t: Substring = s[...] let u: String = ^t print(u)
Avatar
omochimetaru 13-Dec-17 06:01 AM
えーっと、値として返せばいいパターンはそうなんですけど
06:01
Arrayが内部のポインタを返すやつとかって
06:02
API仕様上はwithUnsafeBufferPointerのクロージャの内部の期間だけ有効
06:02
っていうルールになっているんですよね
06:02
Arrayが内部で直列なバッファを持っていなくても
06:02
このwithXXXXの間だけそれを一時的にヒープ上に生成してわたしてやって
06:02
その呼び出しが終わったらまたスパースなメモリレイアウトだけに戻る
06:02
っていう実装が許されていて
06:02
それを考慮すると現状のArray to pointer変換ってただの型変換じゃなくて
Avatar
koher 13-Dec-17 06:03 AM
Arrayが内部で直列なバッファを持っていなくても
そんなことあるの?
Avatar
omochimetaru 13-Dec-17 06:03 AM
strlen(str) // 元のコード // 変換先のコード str.withUnsafeBufferPointer { strlen($0) }
06:03
こういう、関数呼び出しそれ自体をラップする形の書き換えが必要で
06:04
そのケースについては現状の言語仕様上でできるユーザー定義演算子だと無理だと思うんですよね
06:04
The pointer passed as an argument to body is valid only during the execution of withUnsafeBufferPointer(_:). Do not store or return the pointer for later use.
06:05
↑ここで渡されるバッファポインタは、withUnsafeBufferPointerの呼び出しの間だけ有効で、ストアしたりreturnして取り出して後から使ってはいけない
06:05
って書いてあるんですよ
06:05
ということは逆に言うと
Avatar
koher 13-Dec-17 06:05 AM
ん?
strlen(^substr) // 元のコード // 変換先のコード (^substr).withUnsafeBufferPointer { strlen($0) }
になるのではなく?
(edited)
Avatar
omochimetaru 13-Dec-17 06:05 AM
普段のメモリレイアウトに制約がないってことになります。
Avatar
rintaro 13-Dec-17 06:06 AM
var ary = [2, 3, 5] func f(_ p: UnsafePointer<Int>) { } f(ary) // は ary.withUnsafeBufferPointer { f($0.baseAddress!) } // の sugar
(edited)
Avatar
koher 13-Dec-17 06:07 AM
普段のメモリレイアウトに制約がない
理論上そうかもしれないけど、それは Array の内部のポインタをそのまま取り回せないようにするのがその意図なんじゃない?( Array をぶっ壊したり、ライフサイクルを超えて取り回したりできてしまうから)
06:08
連続メモリが保証された型としてはわざわざ↑が存在しているので
06:08
The ContiguousArray type is a specialized array that always stores its elements in a contiguous region of memory.
06:09
Arrayはそうでもないってこと・・・?って思ってます。
Avatar
rintaro 13-Dec-17 06:10 AM
NSArray からブリッジされた Array は Contiguous の保証はないという認識です。
Avatar
koher 13-Dec-17 06:10 AM
This contrasts with Array, which can store its elements in either a contiguous region of memory or an NSArray instance if its Element type is a class or @objc protocol.
06:11
自由なメモリレイアウトが実現したいわけじゃないけど、 Obj-C 連携のために泣く泣くこうなってるってこと??
Avatar
omochimetaru 13-Dec-17 06:11 AM
そういう言い方もできますね
Avatar
koher 13-Dec-17 06:11 AM
それとも、 Obj-C 連携以外の余地も残したいのかな? (edited)
Avatar
omochimetaru 13-Dec-17 06:11 AM
逆に言えばObjC以外のブリッジングも
06:11
できるように制約を弱めてあるともいえそう
06:15
まあ言いたかったのは
06:15
こういうケースがあるから
06:15
型変換マジック演算子を自作できない場合があるということです
Avatar
koher 13-Dec-17 06:16 AM
↓はできたよ。
import Foundation prefix operator ^ prefix func ^(value: Substring) -> String { return String(value) } let s = "abc" let t: Substring = s[...] let u: String = ^t print(u) print(strlen(u)) // OK: 3 print(strlen(^t)) // OK: 3
Avatar
omochimetaru 13-Dec-17 06:16 AM
Substringはいけると思います。
06:16
あ、でもあれか、
Avatar
koher 13-Dec-17 06:16 AM
ArraySliceArray にせよ、変換してから渡すから問題ないのでは?
Avatar
omochimetaru 13-Dec-17 06:16 AM
「引数部分だけに適用できる」ってルールがあったほうが明確なのかな
Avatar
koher 13-Dec-17 06:16 AM
mutating じゃないといけないときはダメだけど。
Avatar
hiragram 14-Dec-17 02:21 AM
import UIKit protocol ProtocolA {} class CustomCell: UITableViewCell, ProtocolA {} func hoge<T>(cellType: T.Type) where T: UITableViewCell & ProtocolA {} let typeA: (UITableViewCell & ProtocolA).Type = CustomCell.self let typeB: CustomCell.Type = CustomCell.self hoge(cellType: typeA) // error: generic parameter 'T' could not be inferred hoge(cellType: typeB) // ok
こういうもんなのか
02:23
func fuga(cellType: (UITableViewCell & ProtocolA).Type) {} fuga(cellType: typeA) // ok fuga(cellType: typeB) // ok
ジェネリクスじゃなくしたら行けた。
Avatar
norio_nomura 14-Dec-17 02:24 AM
プロトコル自身がジェネリックのプロトコル制約を満たせない、っていうやつかな? (edited)
Avatar
hiragram 14-Dec-17 02:25 AM
具体型じゃないと〜というやつですかねえ
02:25
🤔
Avatar
tarunon 14-Dec-17 02:30 AM
これは、そうだね
02:31
もっとシンプルなのでいくとclassの制約の型パラにはclass制約を満たすprotocolの変数は入れられない
02:32
swiftのprotocol型の変数が、実際には存在型として振る舞ってるという話だけどまだ全貌掴めてないや
Avatar
hiragram 14-Dec-17 02:32 AM
ふーむ
Avatar
omochimetaru 14-Dec-17 02:33 AM
こういうもんなのか
定期的に困るけどそういうもんやな
Avatar
hiragram 14-Dec-17 02:33 AM
初めて実際にアプリのコード書いててこれ困ったかも
Avatar
omochimetaru 14-Dec-17 02:34 AM
ひらりの最初に張ったコードであれば
02:34
hoge(cellType: CustomCell.self)
02:34
↑これはとおるよ
02:34
いったん変数に入れるから駄目なだけで。
Avatar
hiragram 14-Dec-17 02:34 AM
うんうん
Avatar
omochimetaru 14-Dec-17 02:34 AM
メタクラスのtype erasureってもしかして自作できない・・・?
Avatar
hiragram 14-Dec-17 02:35 AM
何がしたかったかというとUITableViewのregisterのジェネリックな版みたいなのを作っていて、登録対象のセルの型を [UITableViewCell & ProtocolA).Type] に詰めてforEachで全部処理しようとしたら詰まったという感じです
Avatar
tarunon 14-Dec-17 02:36 AM
やったことないからパッとわからんけど、static func定義されたprotocolのerasureはうまくいかなかったから同様に難しそう
Avatar
koher 14-Dec-17 02:36 AM
前にも話したのは覚えてて結論を覚えてないんだけど、プロトコルが自身のプロトコルを満たさないのってなんでなんだっけ??
Avatar
tarunon 14-Dec-17 02:36 AM
存在型として振る舞っている、存在型はconformできない の二点セット
02:37
結論は…各々の宿題になってますね(やってない)
Avatar
koher 14-Dec-17 02:37 AM
existential が conform できないのの理由ってあるんでしたっけ?現状の実装がそうなってるだけなのか、思想的な理由なのか。 (edited)
Avatar
omochimetaru 14-Dec-17 02:37 AM
登録対象のセルの型を [UITableViewCell & ProtocolA).Type] に詰めてforEachで全部処理しようとしたら詰まった
これは ProtocolA がstatic funcをもってるってこと?
Avatar
tarunon 14-Dec-17 02:38 AM
理論上という話だったので素直な実装だと無理ということだと認識してます
Avatar
omochimetaru 14-Dec-17 02:38 AM
それとも init で作られたオブジェクトが ProtocolA であることを要求してる?
Avatar
hiragram 14-Dec-17 02:38 AM
これは ProtocolA がstatic funcをもってるってこと?
static varがある
Avatar
tarunon 14-Dec-17 02:38 AM
@hiragram それ無理筋なのでgybで複数引数いっぱい生成したらいいよ
Avatar
hiragram 14-Dec-17 02:39 AM
gybまで引っ張り出さなくても感はある
Avatar
tarunon 14-Dec-17 02:39 AM
せいぜい10種類でしょ
02:39
いや手書きはだるいw
Avatar
hiragram 14-Dec-17 02:39 AM
registerメソッドを10回呼べばいいので
02:39
オーバーロードを生成する必要はないかな
Avatar
tarunon 14-Dec-17 02:39 AM
まあそやね
Avatar
omochimetaru 14-Dec-17 02:40 AM
ああそういう感じか
02:40
10個配列に入れといてループで突っ込めたら良かったのにってことか
Avatar
hiragram 14-Dec-17 02:40 AM
そう
Avatar
tarunon 14-Dec-17 02:40 AM
あれに関していうとbind時にregisterごと解決できると言うアイディアはあったんだけど、class/nibのどっちを登録するべきなのか、tableViewのnibで定義済みなのか、が見分けられなくて結局断念した
Avatar
hiragram 14-Dec-17 02:40 AM
それができなくてもまあregister呼び出しが10行になるだけだからそんなに大困りしているわけでもない
02:41
ふむふむ
Avatar
koher 14-Dec-17 02:41 AM
Generalized Existential で Any<Error> が許されるようになれば T: ErrorAny<Error> を入れられるようになるのかな??
Avatar
hiragram 14-Dec-17 02:41 AM
確かに見分けは無理そう
Avatar
omochimetaru 14-Dec-17 02:41 AM
うーんヒラリのやつはなんか簡単なコードでうまく解決したいな
Avatar
koher 14-Dec-17 02:41 AM
てか、それができないと typealias AnySequence<Element> = Any<Sequence where .Iterator.Element == Element> が成り立たないか。
Avatar
tarunon 14-Dec-17 02:41 AM
前回の結論は、それはそうですね、どうなるんでしょうでおしまい
🙏 1
Avatar
koher 14-Dec-17 02:42 AM
なるほど・・・。話したことの記憶しか残ってない・・・。
Avatar
tarunon 14-Dec-17 02:42 AM
でもそれを認めるなら、MyProtocol.self is MyProtocol.Type はtrueでなければならない、型システムを大きく書き換えないといけない
02:42
ABI安定化が遠のく
Avatar
koher 14-Dec-17 02:45 AM
うーん、↓ができないと Generalized Existential の意味あまりなさそう( AnySequence 等の個別の実装をなくせない)だし、
typealias AnySequence<Element> = Any<Sequence where .Iterator.Element == Element>
でもそのために早期 ABI 安定化ができないのだとすると、どちらかを諦めるしかなさそうですね。
Avatar
tarunon 14-Dec-17 02:45 AM
あー、
02:46
現状のMyProtocol.selfは存在型のままで、Any<MyProtocol>.selfは一般的なtype-eresure、とすれば解決はできそうだ
Avatar
koher 14-Dec-17 02:47 AM
うーん、逆な気がしてます。 generalized existential はあくまで existential で、 type eresure を使わなくていいようにしたいけど、そのためには今の実装では無理だからすぐにはできない、じゃないですか?
02:48
generialized existential が導入されたらプロトコルを型として使うのすべて禁止して、 Any<FooProtocol> の形に統一するのがいいんじゃないかと思ってます。
02:49
今も Selfassociatefdtype を持つプロトコルは型として使えないのに、一部のプロトコルが型として使えることに気持ち悪さを感じてます。
02:49
protocolinterface ではないので。
Avatar
tarunon 14-Dec-17 02:49 AM
その路線は早期ABI安定化を諦めることになりそう
02:50
まあ何となくですが今の状況では無理だろうな(ABI)という気はしています
Avatar
koher 14-Dec-17 02:51 AM
安定化までせずとも、同一メジャーバージョン間では ABI を保つとかしてくれれば便利にならないでしょうか?
Avatar
koher 14-Dec-17 06:24 AM
Generics Manifesto つまみ食いしかしてなかったけど、ちゃんと見てみたらおもしろいこといっぱい書いてありますね。 https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md
swift - The Swift Programming Language
06:24
Higher-kinded type の構文の例↓
protocol Functor { associatedtype A func fmap<FB where FB ~= Self>(f: A -> FB.A) -> FB }
Avatar
omochimetaru 14-Dec-17 06:25 AM
全部読んであるかと思ってました
Avatar
koher 14-Dec-17 06:27 AM
↓で protocol<P1, P2>Any<P1, P2> ではなく P1 & P2 に置き換えられちゃったみたいだけど、 generalized existential と整合がとれなくなっちゃってる気がするんだけどどうするんだろう・・・。 https://github.com/apple/swift-evolution/blob/master/proposals/0095-any-as-existential.md
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
omochimetaru 14-Dec-17 06:29 AM
P1 & P2 は今もあるプロトコルをそのまま変数の型にできるやつで
06:29
Generalized Existentialになったときに
06:29
associatedvalue があっても大丈夫になって (edited)
06:29
表記がAny<P1, P2> になるのだと思ってます
06:30
associatedtypeか
Avatar
koher 14-Dec-17 06:30 AM
@omochimetaru 元々 Any<P1, P2> という表記で提案されていたのが最終的に P1 & P2 に変更されて採用されてるんです。
Avatar
omochimetaru 14-Dec-17 06:30 AM
でもその元々のやつは
06:30
associatedtypeがあったら駄目で、それ自体はプロトコルを満たさないやつですよね?
06:31
だから、GEneralized Existentialで提案されてる Any<P1, P2> の表記で表される機能とは振る舞いが違うから
06:31
むしろちょうど避けられてて良かったのかなと
Avatar
rintaro 14-Dec-17 06:31 AM
The principle problem identified by community about the proposal is that "Any<T1, T2>” implies very strongly an “any of T1 OR T2” relationship
https://lists.swift.org/pipermail/swift-evolution-announce/2016-June/000182.html
Avatar
koher 14-Dec-17 06:32 AM
なるほど。
Avatar
rintaro 14-Dec-17 06:32 AM
なので、 Any<P1 & P2 where ...> になるんじゃないかと思います。
Avatar
koher 14-Dec-17 06:32 AM
そうするとそのタイミングで P1 & P2 は廃止される?🤔
Avatar
omochimetaru 14-Dec-17 06:33 AM
僕の理想のストーリーだとそう (ただし変数の型の用法だけ)
Avatar
rintaro 14-Dec-17 06:34 AM
Any<P1 & P2> の sugar として残る(残さざるおえない)んじゃないかなー。
Avatar
koher 14-Dec-17 06:34 AM
でもその場合は P1 & P2 is P1 になるってことですよね?まあゆるくなるだけだから互換性はありますが・・・。
Avatar
omochimetaru 14-Dec-17 06:35 AM
あ〜 まあそれでも問題は無いか・・・
06:35
これまでが変だっただけで普通にconformするようになるって視点では見られますね
Avatar
koher 14-Dec-17 06:35 AM
でもそしたらほとんどのケースで Any<P> よりも P が使われそうなのが微妙・・・
Avatar
omochimetaru 14-Dec-17 06:35 AM
そうですね。
06:36
Any< > 表記はただ where を持つときの構文上の必要で使うってなりそう。
Avatar
koher 14-Dec-17 06:36 AM
P を型として書くのは existential であることを意識しないで使ってしまうので廃止してほしい。
06:37
PAny<P> と書かないといけなければ、
func foo<T : P>(_ x: T)
が望ましいものが
func foo(_ x: P)
と書かれるケースが減りそう。
func foo(_ x: Any<P>)
だと気持ち悪さがあるので。
(edited)
Avatar
rintaro 14-Dec-17 06:38 AM
廃止はさすがに source breaking 過ぎるのでハードル高そう
Avatar
tarunon 14-Dec-17 06:39 AM
Delegateが厳しくなりそう
06:39
class UITableView { var delegate: Any<UITableViewDelegate>? }
これは受け入れられるのだろうか
Avatar
koher 14-Dec-17 06:40 AM
しかたないですね🙃
Avatar
tarunon 14-Dec-17 06:41 AM
民が受け入れないことにはw (edited)
Avatar
omochimetaru 14-Dec-17 06:41 AM
@tarunon それ全然ありだと思ってて
06:41
ObjCの時 id<UITableViewDelegate> って書いてたんだよね
Avatar
tarunon 14-Dec-17 06:41 AM
それはそうなんだよね
Avatar
omochimetaru 14-Dec-17 06:42 AM
古き良き正しさに戻ってる感がある
06:42
「型」と「型のみたす制約」は次元の違う概念だから (edited)
Avatar
koher 14-Dec-17 06:42 AM
おお、そんなのあった。 Obj-C のときは何これって思ってたけど、正しかったのか・・・。
Avatar
omochimetaru 14-Dec-17 06:42 AM
そこが曖昧な表記だったせいでみんなSwiftのprotocolで混乱してきたんだと思うんだよなあ (edited)
06:42
@koher はい、あと、 & 記法みたいなのもありますよ。プロトコル2つのandができた。
06:43
プロトコル合成がないSwift2(ぐらい?)のときはObjCのその点の機能で言えば劣化してしまってた
06:44
rintaro - 今日 午後3時38分 廃止はさすがに source breaking 過ぎるのでハードル高そう
まあ実際これだと思うけどね・・・
Avatar
koher 14-Dec-17 06:44 AM
protocolinterface が概念的に違うことについて、公式ドキュメントでちゃんとした説明が必要だ・・・ (edited)
Avatar
omochimetaru 14-Dec-17 06:44 AM
そうですね。
Avatar
rintaro 14-Dec-17 06:45 AM
Sequence<where Element == Int> みたいな 構文になる可能性もありますね。
06:46
P1<where ...> & P2<where ...>
Avatar
tarunon 14-Dec-17 06:46 AM
Any記法に全部置き換えないならそっちのほうがしっくり来るなぁ
Avatar
koher 14-Dec-17 06:47 AM
Sequence<where Element == Int> みたいな 構文
これはなんで Sequence<Int> にしないのかみたいな話を誘発しそうです・・・
Avatar
omochimetaru 14-Dec-17 06:48 AM
まあ protocol は型ではないんだけど、いろいろ外堀を埋めてって、型っぽく使っても壊れないようにしていく(違いを意識できていなくても動くものが作れる)方向を向く って道もありそうで、今のSwiftはそっち気味ですよね
06:48
protocolに static func とか init とか書けるのが特にそう感じる
Avatar
omochimetaru 14-Dec-17 06:48 AM
でも Sequence<where Element == Int> はジェネリクスとの混同でやはりカオスになりそうw
Avatar
tarunon 14-Dec-17 06:49 AM
rustライクなGenerics protocolとは共存できない記法だ
Avatar
koher 14-Dec-17 06:50 AM
@omochimetaru protocolstatic func は必要では? Argo の Decodable とかそれなしに成立しないし。 initstatic func と同じだし。
Avatar
omochimetaru 14-Dec-17 06:51 AM
必要なのは必要なんですけど
06:52
Scalaで型クラスをやった時の構成法とくらべて
06:52
かなりシンプルというか
06:52
Swiftのprotocol定義はclass構文から直感的に言いたいことがわかるじゃないですか
Avatar
koher 14-Dec-17 06:57 AM
そうかなぁ。 static func を持てるのは制約を表すために普通に必要だと思うけどなぁ。たとえば↓とか。
protocol Group { // 群 static func •(lhs: Self, rhs: Self) -> Self // 結合法則を満たす演算 static var identity: Self { get } // 単位元 var inverse: Self { get } // 逆元 }
(edited)
Avatar
omochimetaru 14-Dec-17 06:59 AM
例えば Java だと interface は static func 制約をかけないし
06:59
Haskellだと
class Eq a where (==), (/=) :: a -> a -> Bool x /= y = not (x == y)
07:00
関数が基本形になっているから、static func相当のことは、2引数関数になるんですけど
07:00
Swiftのprotocol構文は オブジェクト指向言語的に
07:00
メソッドが前提になっていて
07:00
メソッドが前提っってことは第1引数のthisがあるから
Avatar
koher 14-Dec-17 07:00 AM
Java の interfaceprotocol とは別の概念だから異なってていいのでは? (edited)
Avatar
omochimetaru 14-Dec-17 07:00 AM
それが無いstatic funcは一歩戻ってわざわざ書けるようにしている
07:01
いや
07:01
Swiftの構文がうまくできすぎていて自然すぎるから
07:01
当たり前のことのように見えるだけで
07:01
これまではうまく設計できなかったものを
07:01
OOP目線で発明できたって僕は思ってます
07:01
その証拠にSwiftと同じ構文構造の言語が他には無い (edited)
07:02
引き合いとしてScalaが一番わかり易いと思う。
07:02
implicit parameter推論まで持ち出して手書きさせるようになってるけど
Avatar
koher 14-Dec-17 07:03 AM
それは Swift が本質的にオブジェクト指向言語より関数型言語に近いからじゃないかな?
Avatar
omochimetaru 14-Dec-17 07:03 AM
あれはHaskellの型クラスの思想をおダスキー先生がJVM OOPベースで再発明しようとしたときに
07:03
あーゆー形になったわけだけど
07:03
Swiftのアプローチはもっとうまい方法を見つけられたってこと。
07:03
(その代わり型クラス機能としてはSwiftはまだ欠陥が残っているけど)
Avatar
koher 14-Dec-17 07:05 AM
オブジェクト指向言語っぽく書けるうまい構文になってるのはその通りだけど
Avatar
omochimetaru 14-Dec-17 07:05 AM
本質的に関数型なのかどうかは置いといて、従来のオブジェクト指向言語のユーザーが、直感的に触れるようにうまくデザインできている
Avatar
koher 14-Dec-17 07:05 AM
結局理解してないと色々破滅を招きかねないので
07:06
違いを理解することは必要な気がするけどなぁ。
Avatar
omochimetaru 14-Dec-17 07:06 AM
はい、そこで2方向あると思ってて、僕の意見も @koher に近いけど
Avatar
koher 14-Dec-17 07:06 AM
Java から来て一番ひっかかるのの一つは、なんで Sequence<Element> じゃないの?ってとこだろうし。
Avatar
omochimetaru 14-Dec-17 07:06 AM
わからないまま従来のオブジェクト指向言語的な考え方で直感的に使っても
07:06
なんかうごく方向に全部がんばってまとめていく
07:06
っていう道筋もあると思ってて
07:07
現状はどちらも満たしてると思うんですよね
Avatar
koher 14-Dec-17 07:07 AM
Sequence<Element> はでも結局不可能で
Avatar
omochimetaru 14-Dec-17 07:07 AM
Generalized Existenailの Any記法と さっきの Sequence<where> の記法とかはそこの方向性の違いであると思う
Avatar
koher 14-Dec-17 07:07 AM
Iterator もあるから
Avatar
tarunon 14-Dec-17 07:07 AM
上から順番に当てはめるというルールにして、指定しない場合はアンスコとかやれば
Avatar
koher 14-Dec-17 07:08 AM
Sequence<where Element == Int> にしたとして、なんで Sequence<Int> じゃないの?ってなって
Avatar
tarunon 14-Dec-17 07:08 AM
Sequence<Int, _, _>みたいにできるが…?
Avatar
koher 14-Dec-17 07:08 AM
結局理解が必要そうな気が (edited)
Avatar
tarunon 14-Dec-17 07:08 AM
果たしてこれはw
Avatar
koher 14-Dec-17 07:09 AM
それに自分でプロトコル作るときは
protocol Sequence<Element> { ... }
とはできないからやっぱり混乱するだけじゃないかなぁ。
Avatar
tarunon 14-Dec-17 07:09 AM
結局AssoctypeとGenericsの境界があるので、変数宣言時の記法だけGenericsに寄せると結構厳しい気はしてきた
Avatar
omochimetaru 14-Dec-17 07:09 AM
@tarunon associatedtypeって相互に推論されて減ったりしてない?
Avatar
tarunon 14-Dec-17 07:09 AM
どういうことや
Avatar
omochimetaru 14-Dec-17 07:10 AM
えーっと、
Avatar
tarunon 14-Dec-17 07:10 AM
ああ、指定されなくても決まる場合があると
07:10
でもその場合はデフォルトの挙動でしかないから上から押さえつければ別のものを設定できる
Avatar
omochimetaru 14-Dec-17 07:10 AM
Collectionだけでも IndexDiistance, Indices, Iterator, SubSequence
07:11
の4つがあって
07:11
いやいや
07:11
Sequence<T1, T2, T3>
07:11
の表記の問題点は
07:11
左からしか埋められなくて、省略する方が右に限られることで
Avatar
tarunon 14-Dec-17 07:11 AM
07:11
省略は_だぞ
Avatar
omochimetaru 14-Dec-17 07:11 AM
はい
Avatar
tarunon 14-Dec-17 07:12 AM
別に右に限らなくない?
Avatar
omochimetaru 14-Dec-17 07:12 AM
_を適切な個数埋めないといけない
Avatar
tarunon 14-Dec-17 07:12 AM
それはそうじゃろ
Avatar
omochimetaru 14-Dec-17 07:12 AM
今はそうじゃないよね
Avatar
tarunon 14-Dec-17 07:12 AM
僕の提案はSequence<T>の記法は無理、なのでやるにしても_で埋めるしか無い、という話 (edited)
07:14
assoctypeの制約をwhere以下に書くのはまあ既存のconditionの記法もそうだし理解できるとして、<>が出てくるから似た機能のGenericsが想起されて混乱する (edited)
07:14
結論: 括弧が足りない
Avatar
omochimetaru 14-Dec-17 07:15 AM
型名の [ ] はArrayに使っちゃったしなあ
07:16
ブレースはinitの後置クロージャに見えちゃうし・・・
Avatar
tarunon 14-Dec-17 07:16 AM
Sequence[where .Element == Int]
07:16
Arrayとconfuseするかいな?
Avatar
omochimetaru 14-Dec-17 07:17 AM
まあArrayは型名に後置できないからギリギリコンパイラにはわかるだろうけどtypoしたときの混乱がやばそうね
07:17
あれ?丸括弧が残ってんじゃない?w
Avatar
tarunon 14-Dec-17 07:17 AM
それはinitに見えるのでは
Avatar
omochimetaru 14-Dec-17 07:17 AM
あ〜
07:17
なるほど。
Avatar
tarunon 14-Dec-17 07:18 AM
GenericsとのConfusingはマジで概念レベルでトチるので危険きわまりない、角括弧にして誤解を減らせるのはありそうな気がする
Avatar
omochimetaru 14-Dec-17 07:18 AM
結局そうなって初心者が無限に混乱する展開がめっちゃ思い浮かぶ・・・
Avatar
rintaro 14-Dec-17 07:21 AM
let array: [Sequence[where Element == Int].Type] = [Sequence[where Element == Int].self] んー、なんとかいけるか?
Avatar
omochimetaru 14-Dec-17 07:22 AM
Arrayと組み合わせた時の見た目ヤバイですねw
Avatar
tarunon 14-Dec-17 07:22 AM
objective-cを思い出した
Avatar
rintaro 14-Dec-17 07:24 AM
ちなみに let a: Int[] = [1] は未だに Fix-it 出してくれるという親切さ。
Avatar
omochimetaru 14-Dec-17 07:24 AM
ほんとだw
07:24
直せたw
Avatar
koher 14-Dec-17 07:25 AM
Int[] の時代とかありましたね。 Java から来るとわかりやすかったけど、今となっては何がよかったのか・・・
Avatar
koher 14-Dec-17 08:23 AM
AnyIteratorstruct なんだけど、値型捨て過ぎなのでもう class になった方がいいのでは?
let a = [2, 3, 5] let i = AnyIterator(a.makeIterator()) let j = i print(i.next()) // Optional(2) print(j.next()) // Optional(3)
Avatar
omochimetaru 14-Dec-17 08:25 AM
AnyIterator自体のコピーは内部のboxの共有になってそうですね。
Avatar
koher 14-Dec-17 08:25 AM
はい。 struct なのに letnext できてることからも。
08:26
nextmutating func じゃないという潔さ。
Avatar
omochimetaru 14-Dec-17 08:26 AM
ほんとだ
Avatar
koher 14-Dec-17 08:26 AM
意図的なんだろうけど、もう class にしなかった意味がよくわからない。
Avatar
omochimetaru 14-Dec-17 08:27 AM
僕はなんかそこらへんの振る舞いがモヤモヤするしフィールド数でコピーコストが伸びるのが嫌でerasure をclassにする事がよくあります
08:27
ただ、スマートポインタ型としてのイレイジャなのだという解釈であればstructでもいいんですけどね
Avatar
koher 14-Dec-17 08:28 AM
うーん、ただ罠なようにも感じるけどなぁ。
Avatar
omochimetaru 14-Dec-17 10:35 AM
Swift Forums
10:36
Although I posted about this topic before, let me post this again because I think it is important and I have received just few replies. Sorry if I missed some discussion about it. In the proposal ( https://gist.github.com/lattner/429b9070918248274f25b714dcfc7619 ), beginAsync has the following signature. func beginAsync(_ body: () async throws -> Void) rethrows -> Void However, I think it is better to forbid body to throw errors, that is to say, to change its signature to the followi...
10:36
過去ログも移行されている
👏 4
Avatar
koher 14-Dec-17 10:37 AM
Sign Up した。
Avatar
omochimetaru 14-Dec-17 10:37 AM
github連携でログインできるの良い
Avatar
tarunon 14-Dec-17 10:37 AM
アクティベーション町になった
Avatar
omochimetaru 14-Dec-17 10:37 AM
なんかそれリロードしてLoginしたらいけた
Avatar
koher 14-Dec-17 10:38 AM
うん
10:38
メール来なかった
Avatar
tarunon 14-Dec-17 10:38 AM
いけたわ、thx
Avatar
koher 14-Dec-17 10:40 AM
unread が可視化されたおかげで見逃しに気づいた
10:40
Sorry, I'm just getting into this conversation late and am by no means experienced in the area, but why can't the one where you don't want the caller to wait for the result be spelled async -> Never? Theoretically, async -> Void means you're awaiting a result with only one possible value, but if you're not waiting at all, then there is truly no result, yes? ··· On Sun, Nov 12, 2017 at 9:27 AM, Yuta Koshizawa via swift-evolution < swift-evolution@swift.org> wrote: Sorry, I had got s...
Avatar
omochimetaru 14-Dec-17 10:41 AM
これアイコンが青く光ってるのって
10:41
今見てるって意味かな?
Avatar
koher 14-Dec-17 10:42 AM
アイコンが青く光る??
Avatar
omochimetaru 14-Dec-17 10:42 AM
Send me email notifications even when I am active on the site
設定にもこういうのあるし
10:43
ao
10:43
レスごとの未読管理はスクロールするだけで既読になるのか
Avatar
koher 14-Dec-17 10:57 AM
お、ほんとだ、光ってる
Avatar
norio_nomura 14-Dec-17 11:14 AM
GitHub経由でSignUpしたらユーザー名がNorio_Nomuraになってしまってモヤモヤする…😕
Avatar
tarunon 14-Dec-17 11:16 AM
僕もお役所ネームだw
Avatar
mono 15-Dec-17 03:28 AM
GitHubで何度やってもエラーになったので、メールで登録したら結果オーライでmono取れました( ´・‿・`)
Avatar
koher 15-Dec-17 03:29 AM
ID 変更できないの辛い・・・。
Avatar
tarunon 15-Dec-17 03:29 AM
それ
03:29
githubから本名拾ってIDにセットするの絶対おかしい
Avatar
omochimetaru 15-Dec-17 03:29 AM
Username?
Avatar
koher 15-Dec-17 03:30 AM
なんで GitHub の ID じゃなかったんだ?
03:30
Username
03:30
Username Yuta_Koshizawa People can mention you as @Yuta_Koshizawa
03:30
ひどい・・・
Avatar
omochimetaru 15-Dec-17 03:31 AM
メンションがそれになっちゃうのか
Avatar
koher 15-Dec-17 03:33 AM
Discourse の仕様なんだろうか。どうにかしてほしい・・・。
03:33
GitHub と異なるってわかりづらすぎる。
Avatar
omochimetaru 15-Dec-17 03:33 AM
僕はgithubのnameは omochimetaru なんですけど
03:33
フォーラムのIDは omochi.metaru になっていて
Avatar
tarunon 15-Dec-17 03:33 AM
Avatar
omochimetaru 15-Dec-17 03:33 AM
このドットどこから来たんだ?
Avatar
koher 15-Dec-17 03:33 AM
本名登録してないからじゃない?
03:33
メールアドレスかな?
Avatar
omochimetaru 15-Dec-17 03:33 AM
メルアドの @ の左はこれですね
03:34
本名登録ってなあに
Avatar
koher 15-Dec-17 03:34 AM
もしかして GitHub からとってなくて
03:34
@omochimetaru GitHub に < 本名 (edited)
Avatar
omochimetaru 15-Dec-17 03:34 AM
Nameの欄は 名字と氏名わかれてないけど
03:34
別にあるんですか?
Avatar
koher 15-Dec-17 03:35 AM
過去に swift-evolution にメール送ったことがある人はメールから自動的にユーザーが作られてて
03:35
GitHub でサインアップしたらそこでひも付けが行われただけなのでは?
Avatar
omochimetaru 15-Dec-17 03:35 AM
それなら自分のケースも筋が通るな
Avatar
koher 15-Dec-17 03:35 AM
で、僕や @norio_nomura さんや @tarunon さんは本名をメールに入れてたからそれベースで作られて
03:36
@omochimetaru は入れてなかったから @ の左の omochi.metaru になった。
Avatar
tarunon 15-Dec-17 03:36 AM
これID新規作成のときしか設定できない
03:36
Github認証だとそこがスキップ
03:36
罠だな
03:36
If you’ve previously sent mail to one of the Swift mailing lists, an account has already been created for you. If you’d like to take control of that account: Click on Sign Up In the Sign Up form, enter the email address that you used on the mailing lists. You can choose to accept the account name that was pre-created for you, or choose a new one You will be prompted to verify your email address. Please file issues/comments/requests at bugs.swift.org under the “Project Infrastructure” compon...
Avatar
koher 15-Dec-17 03:37 AM
@mono さんは過去にメールを送ってないか、もしくは新規生成したせいで過去の自分のメールと紐付けられてないとか。
👀 1
Avatar
tarunon 15-Dec-17 03:37 AM
新規生成時にIDをセットできるとあります
Avatar
omochimetaru 15-Dec-17 03:37 AM
俺もドット消したいなあ
Avatar
tarunon 15-Dec-17 03:37 AM
このスレにリプライ送っておけば良いかな。
Avatar
koher 15-Dec-17 03:38 AM
Please file issues/comments/requests at bugs.swift.org under the “Project Infrastructure” component for tracking.
03:38
こっちかな?
03:39
ちゃんと新規作成で作ったら紐付けられるっぽいから @mono さんは過去にメールを送ってても同じアドレスだったらセーフそう。
Avatar
tarunon 15-Dec-17 03:39 AM
Github認証でID設定がスキップは完全に罠だ
03:39
おこだよ
😡 4
03:43
上がってない。あげよう
Avatar
yutailang0119 15-Dec-17 03:48 AM
新規作成からでGitHub認証問題なかったけど、前システムの時に登録してた人たちは username 変更しちゃうと今までの @ と紐付かなくて困るって話です? (edited)
Avatar
koher 15-Dec-17 03:49 AM
@yutailang0119 前システムは存在しないです。今まで ML だったので。
03:50
今まで ML に投稿したことがあった人に Username が自動で割り当てられてて
Avatar
yutailang0119 15-Dec-17 03:50 AM
あ、MLから自動でユーザー作られてるからってことか
Avatar
tarunon 15-Dec-17 03:50 AM
03:50
これでええんやろか
Avatar
koher 15-Dec-17 03:50 AM
GitHub 認証するとそれを変更するタイミングが存在しなかったってことですね。
03:51
@tarunon
who have post
posted では?
Avatar
tarunon 15-Dec-17 03:51 AM
ども
03:52
中学生より低い英語力なんで添削は助かります
Avatar
yutailang0119 15-Dec-17 03:52 AM
なるほどw
Avatar
koher 15-Dec-17 03:52 AM
account id
システム上 Username と呼んでるみたいなのでそっちの方が混乱がなさそうです。
Avatar
yutailang0119 15-Dec-17 03:54 AM
username 設定の歯車から変更できそうな動きしてるけど、上の問題に該当する人たちはだめなのかな
Avatar
tarunon 15-Dec-17 03:55 AM
変更できないですね
Avatar
koher 15-Dec-17 03:56 AM
こんな感じです。歯車がないように見えます。
Avatar
yutailang0119 15-Dec-17 03:57 AM
なんと、新規の場合はこんな感じで変更できそう
🙄 1
Avatar
tarunon 15-Dec-17 03:57 AM
03:57
まあじゃあそのうち治るっしょ
Avatar
Kishikawa Katsumi 15-Dec-17 04:06 AM
04:06
昨日サインアップしたけど、デフォルトのままでおそらく期待した動作になりました。
04:07
usernameとNameがGitHubのそれと一致している。
04:07
GItHubでサインアップ。
Avatar
omochimetaru 15-Dec-17 04:08 AM
新しいパターンw
Avatar
koher 15-Dec-17 04:08 AM
@Kishikawa Katsumi さんは過去に swift-evolution に投稿したことありますか?
Avatar
Kishikawa Katsumi 15-Dec-17 04:08 AM
あ、そういうことか。swift-evolutionは購読しているけど投稿はないです。
Avatar
omochimetaru 15-Dec-17 04:08 AM
お、じゃあいまのところ、「github登録 かつ 過去に投稿した」
04:08
の人がこの鉛筆マークが出ない状態になっているw
Avatar
yutailang0119 15-Dec-17 04:09 AM
新規の人たちも、投稿したら変更できんくなったりせんかな
Avatar
koher 15-Dec-17 04:10 AM
@tarunon 僕も英語に自信はないですが、とりあえず修正案考えてみました。
Problems happen when someone who have posted mails to the ML in the past sign up using GitHub authentication. They hope to change their username, but cannot do it after once their accounts were created. I wish there were some additional explaination in the sign up screen, and to get a chance to change the username even if signup is done using github authentication.
👀 1
Avatar
tarunon 15-Dec-17 04:10 AM
全然違うw
04:11
外出てるし帰ったら差し替えよう
04:11
↑のときは何も残ってなさすぎて衝撃を受けた。
Avatar
norio_nomura 15-Dec-17 04:12 AM
今後こういった罠にはまらない様、e-mailのfull nameをnorio_nomuraにしておこうかな…
Avatar
omochimetaru 15-Dec-17 04:49 AM
たしかに。僕も設定しました。
From: omochimetaru <omochi.metaru@gmail.com>
Avatar
rintaro 15-Dec-17 04:54 AM
GitHub 使わずに登録したので希望の id は取れたけど、idの変更は出来ないです。id変更可不可はgithub認証とは関係ないみたい。
Avatar
omochimetaru 15-Dec-17 04:55 AM
Avatar
rintaro 15-Dec-17 04:55 AM
ちなみに過去に投稿したことあります。
🙄 2
04:57
その後メールアドレスを変更したのですが、投稿との関連付けは切れない。また、変更後のアドレスでのMLへの投稿は関連付けられない。
Avatar
norio_nomura 15-Dec-17 05:08 AM
I click the Sign In with GitHub and it was failed. However I can login with my email but there is no choosing my account name for me. I want to change my account name from the pre-created one but I can’t There is no button to change my account appear. However I try to create a new account with my secondary email and the button was shown for that account. Can I change my account name for my main account?
05:08
UpVoteみたいなのはないのね
Avatar
koher 15-Dec-17 05:09 AM
そうか、そういえば待ち状態になってリロードしたけどあれが良くなかった可能性があるな。被害者はみんなそうかも。
Avatar
rintaro 15-Dec-17 05:24 AM
is replying... がリアルタイムで出るのかー。
Avatar
norio_nomura 15-Dec-17 12:33 PM
なんかLikeしただけでは効果が薄そうだったので、自分でも投稿してみた。
Avatar
norio_nomura 15-Dec-17 11:14 PM
ユーザー名変更できる様にしてもらった。
🎉 3
23:17
管理者権限とかで僕だけが変えられる様にしてもらえたのか、全員がそうなのかは不明です。
Avatar
koher 15-Dec-17 11:19 PM
23:20
みんなできるみたいです🙂
👍 2
Avatar
yutailang0119 16-Dec-17 03:19 PM
flattenネタで解決案を求めています https://qiita.com/yutailang0119/items/2f2a871acb687254d3ed ついでに15日目が空いているので、アンサーをぜひ (edited)
これは Swift Advent Calendar 2017 16日目の投稿です。 なんと昨日15日目が空いてしまっています、誰か埋めて...
Avatar
koher 16-Dec-17 03:26 PM
レベル指定はおいといて、ひとまず
しかし、Swift 3.0以降には flatten() は実装されていません。
についてはなくなったのではなく joined にリネームされました。
[[2, 3], [5, 7, 11]].joined()
Avatar
yutailang0119 16-Dec-17 03:28 PM
ほんとですね、知らなかった... どっかで joined() の文字見た気がするのに、無視してました...
Avatar
koher 16-Dec-17 03:29 PM
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
🙏 1
Avatar
koher 16-Dec-17 03:54 PM
@yutailang0119 Swift で↓のように型付けされてない Array を用いるケース自体が稀な気がします🤔
let array: [Any] = [1, 2, 3, [4, 5, 6], [7, [8, 9]]]
15:56
↑のような JSON を作って JSONSerialization でパースすれば↑のような Array が得られるでしょうが、どのようにネストされているか不定なネストした Array を処理するようなことは実用上ほぼないんじゃないでしょうか。
15:57
一方で、 N 重にネストされた Array をすべてつぶして flatten したいようなケースはあると思います。
15:57
[[[1], [2, 3]], [[4, 5, 6]]][1, 2, 3, 4, 5, 6] とか。これならキレイに書く方法がありそうです。
Avatar
koher 18-Dec-17 12:37 AM
この前質問したネーミングの件ですが、 Datawrite(to:options:) に倣って名詞を後ろにおいてもいいだろうということで write(to:formatting:)write(to:format:) としました。ありがとうございました。 (edited)
00:41
--- それとは別に↓を悩んでます。 次のように、extrapolatedBy: を付与することで、 x, y が画像の範囲外にはみ出てしまった場合でも外挿してくれる API を提供しています。
let red = RGBA<UInt8>(red: 255, green: 0, blue: 0, alpha: 255) let pixel = image[x, y, extrapolatedBy: .filling(red)] // 例えば x = -1, y = -1 なら red が返される
(edited)
00:43
この extrapolatedBy に与えているのは ExtrapolationMethod 型の値なのですが、次のように宣言されています。
enum ExtrapolationMethod<Pixel> { case filling(Pixel) // 画像の外側を与えられた値で埋める case edging // 画像の外側を最も近いエッジのピクセルで埋める case repeating // 画像の外側を画像の繰り返しで埋める case reflecting // 画像の外側を画像を鏡写しに折り返して埋める }
(edited)
00:43
これを、 edge, repeat, reflection に変えた方がいい気がしてるんですがいかがでしょうか。 (edited)
00:48
特に edging を縁取り的な意図で使ってるんですが、無限の大きさを持った縁なので 縁取りのイメージと合わない気が。一方で、今のままだと -ing の統一感はあります。
00:49
OpenGL に倣うと clampingToEdge とかになると思うんですがちょっと長すぎかなと。
Avatar
Kishikawa Katsumi 18-Dec-17 04:48 AM
ingじゃない方がいいと思いますね。
04:48
clampingToEdgeとedgeは長いのは気にならないです。
Avatar
koher 18-Dec-17 05:00 AM
ありがとうございます。 extrapolatedBy につながるので、 edge でも意味は通るかなぁとは思うのですが、悩ましいですね・・・。 repeatingreflectingrepeat, reflection にします。 filling-ing でも変じゃないですよね? (edited)
Avatar
Kishikawa Katsumi 18-Dec-17 05:08 AM
fillingでも変じゃないです。
🙏 1
Avatar
koher 19-Dec-17 01:29 AM
あああ、思い出した・・・。 repeat が予約語だったから repeating にしたんだった・・・。
01:30
他だと loop とかかなぁ。
Avatar
omochimetaru 19-Dec-17 01:30 AM
バッククォートで挟むのは?
Avatar
koher 19-Dec-17 01:31 AM
うーん、使う側は .repeat では済むのか。
Avatar
omochimetaru 19-Dec-17 01:31 AM
はい、こまらなそう。
Avatar
koher 19-Dec-17 01:33 AM
画像の繰り返しは repeat の方が一般的かな? CSS や GL も repeat だし。
Avatar
omochimetaru 19-Dec-17 01:34 AM
そう思います
01:35
画像じゃないけど Array.initも repeating だし
01:35
値の繰り返しは repeat って言われてる気がする
Avatar
koher 19-Dec-17 01:36 AM
じゃあ諦めて .repeat にします。
Avatar
t.ae 19-Dec-17 01:37 AM
それ以外だとwrapとか
Avatar
koher 19-Dec-17 01:39 AM
wrap の中身が repeat とかな気が。
GL_TEXTURE_WRAP_S Sets the wrap parameter for texture coordinate ss to either GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER, GL_MIRRORED_REPEAT, GL_REPEAT, or GL_MIRROR_CLAMP_TO_EDGE.
01:42
reflection は GL だと mirror だけど mirror は反射するよりも写し取る(同じものを複製する)的な意味が強い気がするから、 reflection でいいかな? (edited)
01:42
なんか別のライブラリで reflect になってた気がする。
Avatar
t.ae 19-Dec-17 01:42 AM
例によってnumpyからそうじゃないかと思ったんですがGLだとそうなんですね。 wrapって言われると折り返しくらいしか思いつかないので最初見た時なんだこれってなった記憶あります。
01:43
numpyはreflectだったかな
01:44
skimageとかも同じ命名なのですがndarrayをベースに考えられてるはずなので一般の画像処理ライブラリとはずれてるかもしれない……
Avatar
koher 19-Dec-17 01:45 AM
numpy だと constant かぁ。確かに filling(Pixel)constant(Pixel) にしてもいいかも?
01:46
extrapolatedBy: .constant(red) とか。 (edited)
Avatar
omochimetaru 19-Dec-17 01:46 AM
fillのほうがわかりやすいと思いますねえ
01:46
numpyはそもそも画像の文脈じゃなくて数学の文脈で設計されたのを画像の表現に応用してるからちょっとズレてくると思う
Avatar
koher 19-Dec-17 01:48 AM
OpenCV とか参考にすればいいのかなぁ。
Avatar
omochimetaru 19-Dec-17 01:48 AM
こういうのは想定してるユーザ層が馴染みのあるライブラリを参考にするととっつきやすいと思います
Avatar
koher 19-Dec-17 01:49 AM
BORDER_CONSTANT
01:50
うーん、最もメジャーなのがいまや numpy だと思うんだよなぁ。
Avatar
omochimetaru 19-Dec-17 01:51 AM
ちょろっとやるならimagemagickとかPILだと思う
Avatar
t.ae 19-Dec-17 01:51 AM
ExtrapolationMethodconstantだとちょっと違和感ある気がしますね。 Paddingconstantだとしっくりくるんですが
Avatar
omochimetaru 19-Dec-17 01:51 AM
あとSwift的にはCoreGraphicsか。
01:52
numpy は機械学習系の人しかやってないんじゃないですか?
01:52
ちょっと画像をリサイズしようとかグレースケール化しようとか思ってnumpy使うイメージが無い (EasyImageyのユースケースは↑こういうのなのかな?と思っている)
01:53
サービスとかでアップされた画像をサムネイル用に加工するサーバサイドのimagemagickとかが
01:53
めちゃめちゃ触られてると思う
Avatar
koher 19-Dec-17 01:53 AM
PIL は padding とかなさそう・・・
Avatar
koher 19-Dec-17 01:54 AM
How to add padding when using imagemagick to convert an EPS into a PNG? I want to do something like: convert logo.eps -size 128x128 logo.png But want the actual logo to be 96x96px, centered,
01:55
お、ないかと思ったらあるのか。
01:55
color はないなぁ。 color に限らないし。
Avatar
t.ae 19-Dec-17 01:55 AM
そもそもモードがいろいろ無さそうですね
Avatar
koher 19-Dec-17 01:56 AM
そもそも extrapolatedBypaddingBy にした方がいいかな?
01:56
interpolatedBy とそろえたかったんだけど。
01:57
paddedBy かな?
Avatar
omochimetaru 19-Dec-17 01:57 AM
そもそも extrapolatedBy を paddingBy にした方がいいかな?
個人的にはそっちのほうがとっつきやすくなりそう。
Avatar
koher 19-Dec-17 01:58 AM
interpolatedBy.nearestNeighbor とか .bilinear とかが続く。
01:59
padding というタームは浸透してるから paddingBy がいいけど、そうすると interpolatingBy も検討しないといけない・・・。
Avatar
omochimetaru 19-Dec-17 02:00 AM
OpenGLはあまり参考にならんなあ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
Avatar
koher 19-Dec-17 02:00 AM
resizedTo(width: ..., height: ..., interpolatedBy: ...) とかもあるからなぁ。
Avatar
t.ae 19-Dec-17 02:00 AM
https://en.wikipedia.org/wiki/Bilinear_interpolation こっちはinterpolationでいい気が
In mathematics, bilinear interpolation is an extension of linear interpolation for interpolating functions of two variables (e.g., x and y) on a rectilinear 2D grid. The key idea is to perform linear interpolation first in one direction, and then...
Avatar
omochimetaru 19-Dec-17 02:00 AM
まあたしかにほんとに補間そのものだよね
Avatar
koher 19-Dec-17 02:00 AM
そもそも interpolating にしたら by でいいのかもわからない・・・。
Avatar
omochimetaru 19-Dec-17 02:01 AM
はみ出しのほうはまあ補外でああるんだけど
02:01
enum ExtrapolationMethod<Pixel> { case filling(Pixel) // 画像の外側を与えられた値で埋める case edging // 画像の外側を最も近いエッジのピクセルで埋める case repeating // 画像の外側を画像の繰り返しで埋める case reflecting // 画像の外側を画像を鏡写しに折り返して埋める }
Avatar
koher 19-Dec-17 02:01 AM
型名は InterpolationMethod です。
Avatar
omochimetaru 19-Dec-17 02:01 AM
関数というより「埋める」気持ちが強く感じられる
Avatar
t.ae 19-Dec-17 02:01 AM
nearest neighborがinterpolateであるかどうかが肝か
Avatar
omochimetaru 19-Dec-17 02:01 AM
こ〜 2次の傾きを維持して伸びていく〜とかあると、補外っぽいんですけど。
02:02
まーreflectingはそんな感じあるか
Avatar
koher 19-Dec-17 02:02 AM
ちなみに↓のような API もある。
subscript(x: Double, y: Double, interpolatedBy interpolationMethod: InterpolationMethod, extrapolatedBy extrapolationMethod: ExtrapolationMethod<Pixel>) -> Pixel
02:03
2次の傾きを維持して伸びていく
そういうのを追加する可能性もある。
Avatar
omochimetaru 19-Dec-17 02:04 AM
フーム
Avatar
koher 19-Dec-17 02:04 AM
↓を考えると subscript のラベルは名詞を並べるだけで良さそうだから https://developer.apple.com/documentation/swift/dictionary/2894528-subscript
Avatar
omochimetaru 19-Dec-17 02:05 AM
「上のエッジと右のエッジで埋め方を変えたい」とかは無いかなあ
Avatar
koher 19-Dec-17 02:05 AM
subscript(x: Double, y: Double, interpolation: InterpolationMethod, extrapolation: ExtrapolationMethod<Pixel>) -> Pixel
とか、 extrapolationpadding とかでいいかもだけど
02:05
うん、それはあり得ると思うんだけど今はサポートしてない。
Avatar
omochimetaru 19-Dec-17 02:05 AM
まあそれでも extrapolatedTopBy とかでいいか
Avatar
koher 19-Dec-17 02:06 AM
いや、やるなら ExtrapolationMethod を改造かなと思ってる。
02:06
全方位、縦横別、各方位くらいの三つにわけて
02:06
そこにさらに今の値を渡すようなイメージ。
Avatar
omochimetaru 19-Dec-17 02:07 AM
ま〜そのほうがいいのかな〜
Avatar
koher 19-Dec-17 02:08 AM
で、利便性のために ExtrapolationMethodcase にも .repeat とかを用意しておいて .all(.repeat) の意味になるとか。で、 .all(.all(...)) とかはダメだから、 .repeat だけを分離した型も必要になる。
02:08
けど、それを言い出したら interpolation も縦は .bilinear で横は nearestNeighbor で、とかあり得るよね。
Avatar
omochimetaru 19-Dec-17 02:08 AM
自力でADT上にショートカットを作ってunionっぽく見せるって感じですね
02:09
そうですねえ
02:09
OpenGLでは拡大と縮小のinterpolationをわけられますしね
02:09
あ、この場合は
02:09
Double Indexだから常に拡大の文脈か
Avatar
koher 19-Dec-17 02:09 AM
ん?縮小もあるよ。
Avatar
omochimetaru 19-Dec-17 02:10 AM
えーっと、subscriptの場合は。
Avatar
koher 19-Dec-17 02:10 AM
あー、 GL だと拡大するか縮小するかわからないけど、画像を操作する場合は常に拡大か縮小かはわかるね。
Avatar
omochimetaru 19-Dec-17 02:10 AM
resizeメソッドがあるならそこでは拡大縮小で処理変えたいとかありえますね
Avatar
koher 19-Dec-17 02:10 AM
あ、 resizedTo の話ね。 (edited)
Avatar
omochimetaru 19-Dec-17 02:10 AM
いや、宛先のサイズがビューのサイズとかなら
02:10
で、送り元がpngのサイズなら
02:10
拡縮のどっちになるかはわからんですね
Avatar
koher 19-Dec-17 02:11 AM
なるほど、操作後のサイズが未知というのはあり得るか。
Avatar
omochimetaru 19-Dec-17 02:11 AM
操作元が未知もあるかと、アプリのユーザーがアルバムから写真を指定するとか。 (edited)
Avatar
koher 19-Dec-17 02:12 AM
とりあえず、今の InterpolationMethodExtrapolationMethod はそのままで、必要に応じて DirectedInterpolationMethod とかを追加するのが良さそう。 .both(.bilinerar), .each(x: .nearestNeighbor, y: .bicubic) とか。
02:12
ネーミングの話は別として。
02:13
Dictionarysubscript[_:default:] に倣うなら subscript[_:_:interpolation:extrapolation:] とかかなぁ。
02:14
@omochimetaru サイズ未知の件は、 API 呼び出す前にサイズで切り分けてで最悪いい気が。
Avatar
omochimetaru 19-Dec-17 02:14 AM
えーでも縦は伸びるけど横は縮むとかもありますよ
Avatar
koher 19-Dec-17 02:14 AM
resizedTo(width:height:) のラベルが難しい・・・
02:15
それは DirectedInterpolationMethod でカバーできる想定で。
02:15
拡大・縮小で指定するよりも軸で指定する方が筋が良さそう。
02:15
すべての組み合わせを用意すると組合せ爆発がすごそう・・・。
Avatar
omochimetaru 19-Dec-17 02:15 AM
そうですねえ・・・
Avatar
koher 19-Dec-17 02:16 AM
これが enum じゃなくて sealed class だったら階層的にサブタイピングでうまいことわけられるんだけどね。
Avatar
omochimetaru 19-Dec-17 02:16 AM
なるほど
Avatar
t.ae 19-Dec-17 02:17 AM
なんかその辺はユーザー側で順番にやってくれって感じがしますが。
Avatar
koher 19-Dec-17 02:18 AM
↓とか?
InterpolationMethod SimpleInterpolationMethod NearestNeighbor Bilinear Bicubic DirectedInterpolationMethod Both(SimpleInterpolationMethod) Each(SimpleInterpolationMethod, SimpleInterpolationMethod)
02:19
拡大・縮小を考えるとさらなる入れ子が必要だけど、 enum よりはキレイに整理できそう。
02:19
一応、 open でない public なクラスを使えば Swift でも同じようなことはできる。
02:21
resizedTo(width:height:interpolation:) は変な気がするけどなぁ。 interpolatedBy とかじゃなくても、 write(to:format:) と同じで別に気にしなくていい? (edited)
02:22
To の後に width, height, interpolation が並列に並ぶのも気持ち悪い。
Avatar
t.ae 19-Dec-17 02:22 AM
そもそも角の外側はどっちが優先かとかも考えないとだめな気がしますけど
Avatar
omochimetaru 19-Dec-17 02:23 AM
たしかにwww
Avatar
koher 19-Dec-17 02:23 AM
resized(to: Size, interpolatedBy: InterpolationMethod) とすることもできるけど、そうすると Size の扱いが面倒。
Avatar
omochimetaru 19-Dec-17 02:23 AM
じゃあ8つの領域にわけて・・・ ・・・
Avatar
koher 19-Dec-17 02:24 AM
ん?そんなことなくない? extrapolation は軸別に考えられるから
02:25
それで外挿された (Int, Int) の点に対して補間するだけでは?
02:26
軸ごとに指定したらダメか (edited)
Avatar
omochimetaru 19-Dec-17 02:26 AM
fillingの場合はだめそうだけど
02:26
repeatingとかはサンプリング座標の変換だからいけそう。
02:27
edgingも座標をmaxで止めてるだけだから軸ごとに処理できますね
Avatar
koher 19-Dec-17 02:28 AM
x 方向と y 方向に別々の extrapolation を考えて一意に定まらないケースがなかなか思いつかない。 filling してもいけそうじゃない?
Avatar
omochimetaru 19-Dec-17 02:28 AM
Xはみ出したら赤、Yはみ出したら青だとして
02:28
画像の右上は赤?青?
Avatar
koher 19-Dec-17 02:29 AM
あー、 filling 同士は考えてなかった。ダメだ。
Avatar
omochimetaru 19-Dec-17 02:29 AM
ですよね
Avatar
koher 19-Dec-17 02:29 AM
その場合は
02:29
境界が斜めになるのでは (edited)
Avatar
omochimetaru 19-Dec-17 02:29 AM
まあ、それでもいいですけど、 123 456 789 で123789を青、46を赤、5を元画像 (edited)
02:29
としたい場合は、やる手段はない
02:29
って事になるけど良いか、駄目か、って話だと思います
Avatar
koher 19-Dec-17 02:30 AM
x, y 別指定に .filling はダメとか。さらに階層が増える・・・。
Avatar
omochimetaru 19-Dec-17 02:30 AM
あと斜めの場合はちょうど斜めの上のピクセルはどっちにするのかちょっと悩みますね、混色する?
Avatar
koher 19-Dec-17 02:31 AM
リサンプリングじゃないから .repeat とかと概念的に違うんだよなぁ。
Avatar
omochimetaru 19-Dec-17 02:31 AM
こういうの考えていくとプログラマブルシェーダは便利だなあと思えてきた
02:31
クロージャを渡せる case custom(f) があって、fが簡単に書ける道具を散らかしておくのが楽かも
Avatar
koher 19-Dec-17 02:32 AM
混色にできる場合はして、できない場合( Bool とか)は .nearestNeighbor の境界上と同じようにどちらかに寄せるとかかな。
02:32
@omochimetaru .custom も考えてる。
Avatar
omochimetaru 19-Dec-17 02:33 AM
customさえあれば細かい場合分けは全部捨てちゃってがんばってクロージャ書いてねで
Avatar
koher 19-Dec-17 02:33 AM
単一ピクセルだと意味ないけど、↓みたいにするときに便利。
image[-100...100, -100...100, extrapolatedBy: .custom(...)]
Avatar
omochimetaru 19-Dec-17 02:33 AM
どうにかなりそう
02:34
(細かいってのはさっきから言ってるコーナーケースのことです 単純なfillとかはのこして。
Avatar
koher 19-Dec-17 02:34 AM
interpolation も extrapolation も custom を作ってとりあえずごまかすか。
Avatar
omochimetaru 19-Dec-17 02:34 AM
コメントで // TODO: implemenet case custom って書いといて
02:35
困った人は自分で書く
02:35
スタイル
02:35
あ、あれです、customケースがです
02:35
caseを追加するという意味じゃなくて。
Avatar
koher 19-Dec-17 02:36 AM
ん? InterpolationMethod とかに case custom を追加する話じゃないの? (edited)
Avatar
omochimetaru 19-Dec-17 02:36 AM
まあ作っておけばいいか。
02:36
いや、なんか、 case custom追加するのは正しい方向だと思うけど、ユーザーが困ってからでいいのかなと思った。
Avatar
koher 19-Dec-17 02:37 AM
それぞれ .custom((Double, Double) -> Pixel).custom((Int, Int) -> Pixel) を追加するだけなので大変ではない。
Avatar
omochimetaru 19-Dec-17 02:38 AM
まあそうか
Avatar
koher 19-Dec-17 02:38 AM
あー、
02:38
interpolation の方を
02:39
.custom((Double, Double, (Int, Int) -> Pixel) -> Pixel) にしないとダメそう。
Avatar
omochimetaru 19-Dec-17 02:40 AM
02:40
そうか、サンプリング座標変換もあるから。
Avatar
koher 19-Dec-17 02:40 AM
でも外挿と組み合わせないときは (Int, Int) -> Pixel が要らないんだよな。
02:40
面倒だ・・・
Avatar
omochimetaru 19-Dec-17 02:40 AM
本質的にややこしいですねえ
Avatar
koher 19-Dec-17 02:40 AM
やっぱ .custom は保留しよう・・・
Avatar
omochimetaru 19-Dec-17 02:41 AM
ww
Avatar
koher 19-Dec-17 02:41 AM
extrapolation にしても、 resample するだけなら (Int, Int) -> (Int, Int) にできるしね。
02:41
.filling 以外はこれで表現できる。
02:42
.filling のために ExtrapolationMethod がジェネリックになってるのもややこしいといえばややこしい。
Avatar
omochimetaru 19-Dec-17 02:42 AM
あーそれだけなんですね。
02:42
型として分けても良いかもしれませんねえ
02:42
サンプリング補間層と値補間層。
Avatar
koher 19-Dec-17 02:43 AM
でも API として複雑すぎると思うんよね。
02:43
interpolation との組み合わせ爆発もするし。
02:43
enum じゃ階層にしてすべて ExtrapolationMethod のサブタイプとかもできないしね。
Avatar
omochimetaru 19-Dec-17 02:43 AM
指定したくなった時に指定できて、デフォルト値がうまく埋まってれば 良いとこ取りができて
02:44
デフォルト引数とかで埋められない場合、構築済みのある種のパターンの値を返す static func があると
02:44
そういう感じにできそう。
Avatar
koher 19-Dec-17 02:45 AM
Int だったら 0 とかそういうこと?
02:45
それは後付した protocolpublic にしないといけない・・・。
Avatar
omochimetaru 19-Dec-17 02:45 AM
えーっと
Avatar
tarunon 19-Dec-17 02:49 AM
enum Foo { case foo case bar case piyo(String) case fuga(Int) static var specificFuga1 = Foo.fuga(1) } Foo.specificFuga1
こんな感じかな
Avatar
omochimetaru 19-Dec-17 02:49 AM
サンプリング補間関数 と 値決定関数があったとして、 1層: 座標変換(エッジのピクセルを取るなど) sample: (Double, Double) -> (Double, Double) 2層: ↑の座標がはみ出していたときは 入力Pixelがnil value: (Pixel?) -> Pixel 3層: ↑のPixelを(4つや8つ)受けて nearest neighbour などの適用
02:49
っていうデータパスになっていて
Avatar
tarunon 19-Dec-17 02:49 AM
よく使うプリセットはstatic varなりstatic funcなりで使いやすいAPIを提供しておいてデータ構造は素直なものになっていれば
Avatar
omochimetaru 19-Dec-17 02:51 AM
2の関数については Pixel Protocol に 空の .init() を 制約しておけば、デフォルト値がとれるかな
02:51
さっきの filling だけが2層の関数で、他は1層なんですよね。
Avatar
koher 19-Dec-17 02:51 AM
@omochimetaru そうです。
02:51
が、 Pixel プロトコルを作ってしまうと
02:52
一番良く使う UInt8 とか Float にプロトコルを後付しないといけないし
Avatar
omochimetaru 19-Dec-17 02:52 AM
あーでもだめだこれ、はみ出した方向別に色が違うとかができないな 2層は value: (Int, Int, Pixel?) -> Pixel か?
02:53
一番良く使う UInt8 とか Float にプロトコルを後付しないといけないし
ああ〜
Avatar
koher 19-Dec-17 02:53 AM
RGBA<Channel> とかは付けれないし RGBA<UInt8> とかだけに付けるには conditional conformance がいる。
02:53
今も内部的にはそういう目的の _Summable っていうプロトコルを持っていて
02:53
その上に内部的にそれを使う層を gyb で生成して、
02:54
公開された API で見るとプロトコル後付されてないように見せてる。
02:54
conditional conformance がサポートされたら、プロトコル外付けを許容すれば gyb を大分排除できるので検討の余地はある。
Avatar
omochimetaru 19-Dec-17 02:54 AM
よく使うプリセットはstatic varなりstatic funcなりで使いやすいAPIを提供しておいてデータ構造は素直なものになっていれば
そうそう、そこで言いたかったのはそういうこと、サンプルコード含め。
Avatar
koher 19-Dec-17 02:54 AM
今は _Summablezero みたいなのを持ってて
02:56
たとえば roteated(by:) では斜めになったときの背景を zero で埋めてる。( gyb で各型ごとに extrapolatedBy: .zero) を付与して呼ぶメソッドを大量生成してる。)
Avatar
omochimetaru 19-Dec-17 02:56 AM
Int だったら 0 とかそういうこと?
(でもこの回答が1ステップ先の議論になってた)
02:57
あれ?任意の型のときはどうしてるんですっけ?
02:57
そのzero。
Avatar
koher 19-Dec-17 02:57 AM
任意の型のときは rotated(by:) は使えなくて
02:57
rotated(by:extrapolatedBy:) じゃないと使えない。
Avatar
omochimetaru 19-Dec-17 02:57 AM
あ〜
02:58
なるほどお・・・
02:58
ExtrapolationMethodは、Pixel型をPixel型クラスに所属させるためのwitness定義のように振る舞っているわけですね
02:58
Scalaならimplicitに渡されれる型(の型クラスcofnromance)に関する付属情報が明示的にわたされてるわけだ (edited)
02:59
アドホックなwitness。
Avatar
koher 19-Dec-17 02:59 AM
ちなみに、 numeric な型だと rotatedinterpolatedBy 省略で .bilinear が使われるけど、それ以外では .nearestNeighbor が使われるとかなってる。
03:00
本当は .nearestNeighbor ですらなくて、それ相当の計算だけど。 InterpolationMethod が使えるのは _Summable だけだから。( Bool.bilinear しようがない) (edited)
03:01
ただの Numeric でもいけなくて、 UInt8 とか普通に足して平均とったらオーバーフローするから
03:01
必要に応じて一度 IntDouble に変換する処理とかがあって、そのあたりが全部 _Summable で抽象化されてる。複雑・・・。
03:02
でも、実装は複雑だけど、 public な API はシンプルに保ててるはず。
03:03
他にも↓で COW と box 方式の type erasure を使ってたり、 EasyImagy の実装が( gyb や protocol extension 含め) Swift の技の見本市みたいになってる・・・。 https://github.com/koher/EasyImagy/blob/dev-0.4.0/Sources/EasyImagy/AnyImage.swift (edited)
EasyImagy - Makes it easy to process images in Swift
03:06
AnyImage も元は要らなかったんだけど、 image[-100...100, -100...100, extrapolatedBy: ...] の結果を ImageSlice で返そうとすると、 ImageSlice が内部に持つのが Image だけじゃダメになって、 ImageSliceAnyImage を持つ必要に迫られた。
Avatar
tarunon 19-Dec-17 03:17 AM
見本市w
Avatar
rintaro 19-Dec-17 05:05 AM
https://forums.swift.org のアカウントがリセットされている?
Swift Forums
Avatar
tarunon 19-Dec-17 05:08 AM
05:08
SignUpして変更できた
Avatar
koher 19-Dec-17 05:15 AM
"with GitHub" を押すのは過ちを繰り返すことになるかな?土曜くらいに Username 変更できるようになってたけど。
Avatar
tarunon 19-Dec-17 05:32 AM
Username葉変更できるけどinitialは拾ってきてくれないですね
Avatar
koher 19-Dec-17 06:56 AM
普通に GitHub 連携して後から変更できた🙂
Avatar
norio_nomura 19-Dec-17 11:01 AM
数日前に「消去した」ってメッセージが出てましたよ。>forums (edited)
👍 1
Avatar
koher 21-Dec-17 02:40 AM
Swift Advent Calendar の 12/12 分が投稿されてないようです。そのため、ランキングにも参加できていません。どなたか代わりに投稿しませんか? https://qiita.com/advent-calendar/2017/swift
Taylorじゃない方のSwiftです( ´・‿・`) - その2: Swift その2 Advent Calendar 2017 - Qiita - サーバーサイド: [Server Side Swift...
Avatar
lovee 21-Dec-17 02:42 AM
書きたい…時間あったら…(白目
Avatar
omochimetaru 21-Dec-17 02:42 AM
その1が埋まってないならその2の人が引っ越したらいいんでは?
Avatar
lovee 21-Dec-17 02:42 AM
ちなみにすでに2つものAdvent Calendar記事遅れてます…
Avatar
omochimetaru 21-Dec-17 02:42 AM
その2は穴が5こぐらいあったから両方埋まらないよりはマシ
Avatar
lovee 21-Dec-17 02:43 AM
なんとか週末に遅れを取り戻したい
02:43
書けたら書きます
👍 1
Avatar
koher 21-Dec-17 02:43 AM
loveeさんはその2にいるのか。
Avatar
lovee 21-Dec-17 02:44 AM
います、1が埋まってたから2の方に登録してました
02:44
でもどうせなら2と別の記事書きたい
Avatar
koher 21-Dec-17 02:44 AM
引っ越しでもいい気も。
Avatar
lovee 21-Dec-17 02:45 AM
まあ別に両方書いちゃダメなんてことはないので、週末に頑張って仕上げます
👍 2
Avatar
koher 21-Dec-17 05:49 AM
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
omochimetaru 21-Dec-17 05:50 AM
My first evolution proposal is under review - SE-0193 cross module inlining and specialization: https://t.co/MzUWxtYumh
05:51
slavaにとって実は1発目らしい
05:51
これ読みましたけど abiPublic は実態をストレートにあらわしていて良い命名だと思った
Avatar
koher 21-Dec-17 06:01 AM
internal なメソッドでも @abiPublic でインライン化できるのか。
Avatar
omochimetaru 21-Dec-17 06:01 AM
そうです!
06:02
前回の下書きproposalだとinlineableだけで投げられたけど、結局 両方一気に来ましたね。
Avatar
koher 21-Dec-17 07:19 AM
それがないと辛いもんね。
Avatar
lovee 24-Dec-17 04:07 PM
だいぶ遅くなったけどなんとか書きました(´ཀ`」 ∠) https://qiita.com/lovee/items/257abf17cccea8293d0f
# はじめにのはじめに 大変遅くなって申し訳ないです。この記事は Swift その2 Advent Calendar 2017 23 日...
👏 7
Avatar
takasek 28-Dec-17 12:35 PM
Decimal型を有効活用してる方いらっしゃいますか? APIが使いづらいし、表示したいだけならNumberFormatterで事足りるし、 一体こいつの存在意義はあるんだろうか…と思いまして、 みなさんの利用例が気になりました 辛いAPI👇
let double: Double = 3.123456 // 3.123456 var dec1 = Decimal(double) // 3.123456000000000512 var dec2: Decimal = Decimal() NSDecimalRound(&dec2, &dec1, 4, .bankers) dec2 // 3.1235
隠蔽してみた👇
extension Decimal { func rounded(exponent: Int, roundingMode: RoundingMode = .bankers) -> Decimal { var me = self var result = Decimal() NSDecimalRound(&result, &me, exponent, .bankers) return result } } dec1 // 3.123456000000000512 dec1.rounded(exponent: 4) // 3.1235
Avatar
Kishikawa Katsumi 28-Dec-17 12:38 PM
典型的なのは金額の計算ですね。浮動小数では扱えないのでDecimalを使います。レジの実装とか。あとは電卓など。
Avatar
banjun 28-Dec-17 12:38 PM
NSDecimalNumberとは別物なんですか?
Avatar
Kishikawa Katsumi 28-Dec-17 12:40 PM
DecimalとNSDecimalNumberはDateとNSDateの関係と一緒じゃないですかね。
Avatar
takasek 28-Dec-17 12:40 PM
Doubleで大抵は誤差が出ないだろうけれど、その万一も防止したい場合に使う、という感じでしょうか
Avatar
tarunon 28-Dec-17 12:41 PM
金額は誤差出ちゃだめな世界なのでDecimalですね
Avatar
Kishikawa Katsumi 28-Dec-17 12:41 PM
やってみたらわかりますけどDoubleだと全然合わないですよ。 (edited)
😮 1
Avatar
tarunon 28-Dec-17 12:41 PM
そもそも浮動小数点は…
Avatar
banjun 28-Dec-17 12:42 PM
NSDecimalNumber,BigInt的な精度があるわけじゃないので,精度でなくて使うのやめた,みたいな謎の記憶がある
Avatar
Kishikawa Katsumi 28-Dec-17 12:42 PM
BigInteger的には残念ながら使えないですね。覚えてないですけど何兆くらいまでじゃなかったでしたっけ。
Avatar
tarunon 28-Dec-17 12:43 PM
中身は64bitIntだった記憶
Avatar
omochimetaru 28-Dec-17 12:43 PM
NSDecimalNumber, an immutable subclass of NSNumber, provides an object-oriented wrapper for doing base-10 arithmetic. An instance can represent any number that can be expressed as mantissa x 10^exponent where mantissa is a decimal integer up to 38 digits long, and exponent is an integer from –128 through 127.
Avatar
takasek 28-Dec-17 12:43 PM
DecimalはReferenceConvertibleではないので、DateとNSDateの関係とは微妙に違いそうですね ただNSDecimalNumber用のenumを使い回してはいるようです https://github.com/apple/swift-corelibs-foundation/blob/ee61823ae71f4c4f9ca157fd290c4b7de915b2a4/Foundation/Decimal.swift
swift-corelibs-foundation - The Foundation Project, providing core utilities, internationalization, and OS independence
Avatar
omochimetaru 28-Dec-17 12:44 PM
10進計算だけど表現は仮数部と指数なんで浮動小数ですね
12:46
十進数表記の少数が誤差なく表現できる(桁が足りてれば)
Avatar
Kishikawa Katsumi 28-Dec-17 12:46 PM
なるほど、そういう話です?つまりNSDecimalNumberのようにはDecimalは使えない?
Avatar
omochimetaru 28-Dec-17 12:46 PM
2進少数では0.1などはそもそも表現できない
Avatar
rintaro 28-Dec-17 12:46 PM
DecimalNSDecimal で c 構造体 みたいです。
Avatar
Kishikawa Katsumi 28-Dec-17 12:47 PM
あ、NSDecimalか。
12:47
NSDecimalを使うことはほとんどないはずなので、その関係だとするとDecimalをほとんど使わないというのは普通だと思います。
Avatar
banjun 28-Dec-17 12:47 PM
Decimalが3種類あるのか
Avatar
Kishikawa Katsumi 28-Dec-17 12:48 PM
で、私は浮動小数と固定十進の一般的な使い分けの話かと思って話しました。
Avatar
tarunon 28-Dec-17 12:48 PM
仮想通貨のアプリ作ってる人は何使ってるんだろ
Avatar
Kishikawa Katsumi 28-Dec-17 12:48 PM
基本単位が大きいですもんね。
Avatar
omochimetaru 28-Dec-17 12:49 PM
無限精度少数を使って適切に丸めるのがセオリーかと
Avatar
Kishikawa Katsumi 28-Dec-17 12:49 PM
NSDecimalNumberでは足りなさそう。
Avatar
tarunon 28-Dec-17 12:49 PM
0.00000012BTCとか結構エグい要求ありますよね
Avatar
rintaro 28-Dec-17 12:49 PM
https://developer.apple.com/documentation/foundation/nsdecimalnumber?language=objc の注意見ると Decimal は NSDecimalNumber にブリッジと書いてあるな。 (edited)
Avatar
tarunon 28-Dec-17 12:49 PM
誤差が出ると困る、全部サーバーでやるのかな
Avatar
omochimetaru 28-Dec-17 12:49 PM
いや、無限に桁が増えていくとどうしようもないから
12:50
金融の世界では少数何桁以下はどういう計算ではどっちに丸めるとか
12:50
決まってるはず
12:50
BTCに関して言えば桁数の最小単位ある
Avatar
tarunon 28-Dec-17 12:50 PM
なるほど
Avatar
omochimetaru 28-Dec-17 12:51 PM
Avatar
Kishikawa Katsumi 28-Dec-17 12:52 PM
レジの消費税はどっちに丸めるかは店の裁量に任されています。(だから作るのが面倒とも言える)
😫 1
Avatar
tarunon 28-Dec-17 12:52 PM
ひゃー
Avatar
omochimetaru 28-Dec-17 12:52 PM
お、じゃあ、客に対しては切り上げて請求して
12:52
会計上は切り下げて記録しておけば
12:52
1円ずつ脱税できますね
Avatar
tarunon 28-Dec-17 12:52 PM
まずいですよ!!
12:53
攻殻機動隊を思い出した
Avatar
Kishikawa Katsumi 28-Dec-17 12:54 PM
まあ、Doubleの誤差とは別に支店がめっちゃあるとかだったらだいぶ違ってきますね。
Avatar
rintaro 28-Dec-17 12:54 PM
消費税は基本的に内税での計算のはず。 売り手は決済毎ではなく期間内売り上げに応じた税を払う。
Avatar
omochimetaru 28-Dec-17 12:55 PM
あ〜 最後にまとめて8%求めるのか。
Avatar
tarunon 28-Dec-17 12:55 PM
そういえばAppleが消費税かっ引いてくれてますが、売り上げ1000万以下なら払わなくていいはずで、取り戻したりできるんですかね?
12:55
swift関係なくなってきたw
Avatar
Kishikawa Katsumi 28-Dec-17 12:57 PM
消費税の丸めが店の裁量というのは1円以下の端数の話です。
Avatar
takasek 28-Dec-17 01:00 PM
も、盛り上がってるとこ済みません… Swiftの話だけまとめると、 - Decimalは固定小数点数 - 38桁の精度までは保証するアルゴリズムって点ではNSDecimalNumberと互換性のある型 って感じですね
13:01
と思ったら、 >https://developer.apple.com/documentation/foundation/nsdecimalnumber?language=objc の注意見ると Decimal は NSDecimalNumber にブリッジと書いてあるな ReferenceConvertibleじゃなくてもブリッジできるんですね
let dec1 = Decimal(double) // 3.123456000000000512 let n = (dec1 as AnyObject) type(of: n) // __ObjC.NSDecimalNumber.Type
Avatar
omochimetaru 28-Dec-17 01:01 PM
いや、どれも浮動小数だと思います
Avatar
rintaro 28-Dec-17 01:03 PM
_ObjectiveCBridgeable っていう ReferenceConvertible の一個下のレイヤーに準拠してますね。
Avatar
takasek 28-Dec-17 01:03 PM
正確にいうなら、内部的には浮動小数点数だけど、桁数固定小数点数に見せるラッパー
13:03
なるほど
Avatar
omochimetaru 28-Dec-17 01:04 PM
いえ、見えないと思います
13:04
浮動小数の特性として、でかすぎる数と小さすぎる数を足し合わせると
13:04
表現桁の幅が足りなくなって何も足さなかった結果になるんですが
13:04
それがDecimal族の間でも起きるはず
13:05
Decimal族が提供してる価値は、十進数基数になってることで
13:05
0.1が0.1になることです
Avatar
takasek 28-Dec-17 01:06 PM
なるほど
Avatar
omochimetaru 28-Dec-17 01:06 PM
FloatとDoubleは2進数少数なので、 0.5や0.25や0.125はあらわせるけど
13:06
0.1や0.12や0.123はあらわせないです
13:07
Decimal族ならあらわせる。
Avatar
Kishikawa Katsumi 28-Dec-17 01:12 PM
let double1: Double = 123456789000000000 let double2: Double = 1 print(String(format: "%.20f", double1)) print(String(format: "%.20f", double2)) print(String(format: "%.20f", double1 + double2)) let decimal1 = Decimal(string: "123456789000000000")! let decimal2 = Decimal(string: "1")! print(decimal1) print(decimal2) print(decimal1 + decimal2)
13:13
^ おもちさんの言ってることってこういう話ですよね? @omochimetaru DecimalはDoubleと同じ結果にはならないみたいですよ。
13:14
123456789000000000.00000000000000000000 1.00000000000000000000 123456789000000000.00000000000000000000 123456789000000000 1 123456789000000001
Avatar
omochimetaru 28-Dec-17 01:15 PM
let decimal1 = Decimal(string: "123456789012345678901234567890")! let decimal2 = Decimal(string: "0.0000000000000000000000000001")! print(decimal1) // 123456789012345678901234567890 print(decimal2) // 0.0000000000000000000000000001 print(decimal1 + decimal2) // 123456789012345678901234567890
Avatar
Kishikawa Katsumi 28-Dec-17 01:15 PM
おお、おっしゃる通りですね。
Avatar
omochimetaru 28-Dec-17 01:15 PM
仮数部の表現精度が38桁あるので、 @Kishikawa Katsumi さんのサンプルだとまだセーフ
Avatar
Kishikawa Katsumi 28-Dec-17 01:16 PM
なるほど。
Avatar
omochimetaru 28-Dec-17 01:16 PM
let decimal1 = Decimal(string: "123456789012345678901234567890")! let decimal2 = Decimal(string: "0.0000000000000000000000000001")! print(decimal1) // 123456789012345678901234567890 print(decimal2) // 0.0000000000000000000000000001 let decimal3 = decimal1 + decimal2 print(decimal3) // 123456789012345678901234567890 print(decimal1 == decimal3) // true!
Avatar
Kishikawa Katsumi 28-Dec-17 01:16 PM
私の環境でも確認しました。
Avatar
omochimetaru 28-Dec-17 01:16 PM
↑このように、trueになるので、文字列化するときに省略されているのではなくて、情報として消えてる。
😱 1
13:17
言い換えると、 Decimalに 0.0000000000000000000000000001 ずつ足していく無限ループを書くと、どっかで増加が止まるってことですね。
13:19
https://ja.wikipedia.org/wiki/倍精度浮動小数点数
通常の数(正規化された数)の精度は、53ビット相当[1](十進に直すと約16桁)である。
Avatar
tarunon 28-Dec-17 01:19 PM
1スタートでも38桁超えたら増加は止まる?
Avatar
omochimetaru 28-Dec-17 01:20 PM
Double型だと仮数部が16桁しかないですね
13:21
Doubleの指数部は11bitだから-1024〜+1024倍が表現できるけど
13:21
Decimalは > –128 through 127. ってかいてあるから、 指数部が 2^8 で8ビット
13:23
let decimal1 = Decimal(string: "1234567890123456789012345678901234567890")! let decimal2 = Decimal(string: "1")! print(decimal1) // 1234567890123456789012345678901234567890 print(decimal2) // 1 let decimal3 = decimal1 + decimal2 print(decimal3) // 1234567890123456789012345678901234567890 print(decimal1 == decimal3) // true!
13:23
40桁で増加しなくなった。39桁だとまだ増加した
Avatar
takasek 28-Dec-17 01:25 PM
おー もはやガヤしかできないですが面白いです
Avatar
omochimetaru 28-Dec-17 01:26 PM
指数部で3bit節約しても仮数部を10進38桁にするには全然ビット数が足りないな?
13:28
https://github.com/apple/swift-corelibs-foundation/blob/master/Foundation/Decimal.swift
fileprivate var __exponent: Int8 fileprivate var __lengthAndFlags: UInt8 fileprivate var __reserved: UInt16 public var _mantissa: (UInt16, UInt16, UInt16, UInt16, UInt16, UInt16, UInt16, UInt16)
160bit
swift-corelibs-foundation - The Foundation Project, providing core utilities, internationalization, and OS independence
13:29
import Foundation print(MemoryLayout<Decimal>.size) // 20
13:29
20バイトですね。
13:29
Decimal1個でFloat5個分のメモリ容量を取る。
Avatar
rintaro 28-Dec-17 01:30 PM
let decimal = Decimal(string: "1234567890")! decimal._exponent // 1 decimal._length // 2 decimal._isNegative // 0 decimal._isCompact // 1 decimal._reserved // 0 decimal._mantissa // (.0 52501, .1 1883, .2 0, .3 0, .4 0, .5 0, .6 0, .7 0)
Avatar
omochimetaru 28-Dec-17 01:34 PM
65536 * 1883 + 52501 = 123456789 ですね
13:35
length 2 は mantissa.0, .1 までを使うことを表してて、exponent = 1 だから それに x10 が1個くっついて1234567890になる。
Avatar
takasek 28-Dec-17 01:36 PM
なるほど 仮数そういうふうに見るんですね
Avatar
takasek 28-Dec-17 02:02 PM
最大値と最小値はこれか
Decimal.greatestFiniteMagnitude // 3402823669209384634633746074317682114550000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 Decimal.greatestFiniteMagnitude._mantissa // (.0 65535, .1 65535, .2 65535, .3 65535, .4 65535, .5 65535, .6 65535, .7 65535) Decimal.leastNonzeroMagnitude // 0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 Decimal.leastNonzeroMagnitude._mantissa // (.0 1, .1 0, .2 0, .3 0, .4 0, .5 0, .6 0, .7 0)
(edited)
Avatar
takasek 28-Dec-17 02:23 PM
と思ったらもう一桁いけた
func truelyLeastDecimal() -> Decimal { var x = Decimal(string: "0.1")! var r = Decimal() NSDecimalPower(&r, &x, 128, .plain) return r } func p(_ d: Decimal) { print("=====") print(d) print(d._mantissa) print(d._exponent) } p(Decimal.leastNormalMagnitude) p(truelyLeastDecimal()) /* ===== 0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 (1, 0, 0, 0, 0, 0, 0, 0) -127 ===== 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 (1, 0, 0, 0, 0, 0, 0, 0) -128 */
Decimalには定義みあたらないけど、NSDecimalNumberのexponentは
exponent is an integer from –128 through 127.
だとすると、leastNonzeroMagnitude, leastNormalMagnitude の実装もしや間違ってるのでは https://github.com/apple/swift-corelibs-foundation/blob/ee61823ae71f4c4f9ca157fd290c4b7de915b2a4/Foundation/Decimal.swift#L120
swift-corelibs-foundation - The Foundation Project, providing core utilities, internationalization, and OS independence
Avatar
omochimetaru 28-Dec-17 02:27 PM
あれ?ほんとだ、もう一個いけそうですね
14:27
ああ @takasek さんの書いてるテストが実際に-128まで攻めたやつなのかw
14:28
This value compares less than or equal to all positive numbers, but greater than zero.
14:29
他のどんな正の数よりも小さいか等しいがゼロよりは大きい だから
14:29
しかし Decimal.leastNormalMagnitude > truelyLeastDecimal() こうなってしまうので
14:29
明らかにバグですね
Avatar
takasek 28-Dec-17 02:30 PM
やった見つけた
Avatar
omochimetaru 28-Dec-17 02:30 PM
すげえw
Avatar
koher 09-Jan-18 01:37 AM
↓書いて思ったんですが、 Swift の文字列補間で CustomStringConvertible じゃないものでも文字列に埋め込めるの良くなくないですか?何でもとりあえず文字列にしたいニーズはあるとして、それはデバッグ用にそういう関数を用意すれば良いだけに思います。 https://qiita.com/koher/items/6c855ddbda8797af4605
あけましておめでとうございます。新年早々おもしろツイートがバズっていました。 おっ、nu...
01:38
CustomDebugStringConvertible を分けてる意味がなくなっちゃってる気が。 printAny をとれるのも微妙。
Avatar
omochimetaru 09-Jan-18 01:38 AM
CustomStringConvertibleとCustomDebugStringConvertibleとあとなんかOutputPRintableだったかなんかへんなやつがあって
01:38
その3つの判定を動的にやったあと
01:38
更に、そのどれでもない場合に
01:39
dump() と同じような挙動で出力する挙動があって
01:39
それが↑のOptional()の形式に至る
Avatar
koher 09-Jan-18 01:39 AM
OptionalCustomDebugStringConvertible だったと思うから
Avatar
omochimetaru 09-Jan-18 01:39 AM
あ、そうなのか。
Avatar
koher 09-Jan-18 01:39 AM
それで『 Optional(2018)年』になってる。
Avatar
omochimetaru 09-Jan-18 01:40 AM
挙動として String.init(describing: Any) だったはずなんで
01:40
個人的にはCustomStringConvertibleだけが埋め込めるようにして、
01:40
そうでないものを埋め込みたい場合には String.init(describing: x) って書けばいいんじゃねえかと
01:40
おもってます
Avatar
koher 09-Jan-18 01:40 AM
うん、そう思う。
Avatar
omochimetaru 09-Jan-18 01:41 AM
それか "\debug() " みたいなのでもいいけど
Avatar
koher 09-Jan-18 01:41 AM
文字列補間になんでも埋められるのは意図した仕様なのかなぁ。初期の頃に適当にやったのが残ってそう。
Avatar
omochimetaru 09-Jan-18 01:41 AM
あ、いや
01:41
Optional は CustomDebugStringConvertible だったと思うから
これってほんとだっけ
01:41
Optional<T> の Tのconformanceに依存するから
01:41
なんかそこが謎の動的判定ロジックが書いてあるんですよ
Avatar
koher 09-Jan-18 01:42 AM
1> let a: Int? = 42 a: Int? = 42 2> a.debugDescription $R0: String = "Optional(42)" 3> a is CustomStringConvertible $R1: Bool = true
Avatar
omochimetaru 09-Jan-18 01:42 AM
TがCustomDebugStringConvertibleならOptional<T>もCustomDebugStringConvertibleみたいな。 Conditional conformanceできれいにしたいってコメントが入ってた
Avatar
koher 09-Jan-18 01:42 AM
あれ?
01:43
なんで CustomStringConvertible が true になるんだ??
01:43
4> a is CustomDebugStringConvertible $R2: Bool = true
01:43
5> a.description error: repl.swift:5:1: error: value of optional type 'Int?' not unwrapped; did you mean to use '!' or '?'? a.description ^ ?
01:44
5> func debugPrint<T: CustomDebugStringConvertible>(_ value: T) { print(value) } 6> debugPrint(a) Optional(42)
Avatar
omochimetaru 09-Jan-18 01:44 AM
Optionalの特別扱いロジック関係のバグな気がする
Avatar
koher 09-Jan-18 01:45 AM
7> func safePrint<T: CustomStringConvertible>(_ value: T) { print(value) } 8> safePrint(a) error: repl.swift:8:11: error: value of optional type 'Int?' not unwrapped; did you mean to use '!' or '?'? safePrint(a) ^
(edited)
01:46
とりあえず、 OptionalCustomStringConvertible ではないけど CustomDebugStringConvertible ではある(↑)。 (edited)
Avatar
omochimetaru 09-Jan-18 01:46 AM
どちらでもないってこと?
Avatar
koher 09-Jan-18 01:46 AM
日本語まちがえたw (edited)
01:46
後者ではある。修正した。 (edited)
01:47
↓を見ても CustomDebugStringConvertible だけ書いてある。 https://developer.apple.com/documentation/swift/optional (edited)
01:49
Conditional Conformance 導入されたらこれも Conditional になるのかな?
extension Optional : CustomDebugStringConvertible where Wrapped : CustomDebugStringConvertible { ... }
Avatar
koher 09-Jan-18 01:49 AM
Debug だから、別に String.init(describing) で変換すればいいのか。 (edited)
Avatar
omochimetaru 09-Jan-18 01:50 AM
public init<T: TextOutputStreamable> (stringInterpolationSegment expr: T) public init<T: CustomStringConvertible> (stringInterpolationSegment expr: T) public init<T: TextOutputStreamable & CustomStringConvertible> (stringInterpolationSegment expr: T)
(edited)
01:51
曖昧さ回避のための&版オーバーロードで中身はTextOutputStreamable扱いだった
01:52
public init<T>(stringInterpolationSegment expr: T) { self = String(describing: expr) }
CustomDebugStringConvertibleのケースはこれに行きそう
(edited)
01:53
さっきのCustomStringConvertibleについては is だけなぜかtrueになるけど
01:53
ジェネリック関数呼び出しの時の制約解決では false 扱い?
Avatar
koher 09-Jan-18 01:55 AM
istrue はバグな気がする。
01:56
8> let b: CustomStringConvertible = a error: repl.swift:8:34: error: value of optional type 'Int?' not unwrapped; did you mean to use '!' or '?'? let b: CustomStringConvertible = a ^ ! 8> let c: CustomDebugStringConvertible = a c: CustomDebugStringConvertible = { payload_data_0 = 0x000000000000002a payload_data_1 = 0x0000000000000000 payload_data_2 = 0x0000000000000000 instance_type = 0x0000000101416700 libswiftCore.dylib`InitialAllocationPool + 80 protocol_witness_0 = 0x00000001013d1b78 libswiftCore.dylib`protocol witness table for <A> Swift.Optional<A> : Swift.CustomDebugStringConvertible in Swift }
Avatar
omochimetaru 09-Jan-18 01:58 AM
なるほど
01:59
てか、元記事の話なんですけど
01:59
警告が出てるのに無視してるのが最大の問題なのは置いといて
01:59
もし、null安全言語じゃなかったら
02:00
警告を出すこと自体が不可能ですよね?
Avatar
koher 09-Jan-18 02:10 AM
@omochimetaru はい。というか、非 null を区別できないから『Optional(2018)年』自体が起こり得ない。『null年』は起こり得るけど。
Avatar
omochimetaru 09-Jan-18 02:12 AM
ですよね。 だから、nullableとnonnullが静的に区別できる機能が言語にあるからこそ、 コンパイラが「nil年」を出す可能性を指摘できるようになった。 それでも無視した。 って状況なので、何も悪くなってないと思う・・・
02:13
「nil年」が出る可能性がある事と「Optional(2018)年」が出る可能性がある事は同一の警告として現れる。 (edited)
Avatar
koher 09-Jan-18 04:21 AM
はい、何も悪くなってないです(良くなってます)。
04:22
でも、最初からコンパイルエラーならこんな問題は起こらなかったし、 String(describing:)debugDescription すればいいんだから、直接埋め込める必要はない気がします。あえて言えば初心者が混乱するくらい??
Avatar
tarunon 09-Jan-18 04:23 AM
CustonStringConvertibleじゃない場合はコンパイルエラー、半年前ぐらいに着手したけどワーニングがエラーになったまま放置してた
04:23
本来の関係ないワーニング
Avatar
omochimetaru 09-Jan-18 04:24 AM
はい、何も悪くなってないです(良くなってます)。
ですよね〜
あえて言えば初心者が混乱するくらい??
コンパイルエラーのメッセージとして 「String(desciribing:) 使ったら?」って出せばいいからそこはダイジョブそう
Avatar
koher 09-Jan-18 04:31 AM
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
04:32
たとえば BoolValueEnumerable でいいし、 ValueEnumerable な associated value を持つ case があってもその enumValueEnumerable でいい気がする。
04:33
enum Foo { case bar case baz(Bool) }
ValueEnumerable になりたかったりしないかな・・・。
Avatar
omochimetaru 09-Jan-18 04:34 AM
bar , baz(false), baz(true) の3要素になるってことですか?
04:35
bazを受け付ける変数の型がうまく書けなくないですか?
04:35
結局Fooになっちゃうからbazのcaseで(Bool)を剥がすパターンマッチが必要に。
Avatar
koher 09-Jan-18 04:35 AM
The compiler will synthesize an implementation of ValueEnumerable for an enum type if and only if: - the enum contains only cases without associated values; - the enum is not @objc; - the enum has an explicit ValueEnumerable conformance (and does not fulfil the protocol's requirements).
04:37
この一つ目のルールに、 associated value が ValueEnumerable のときは生成で良い気が。 CodableCodable なプロパティを持っている場合と同じように。
04:38
@omochimetaru
bazを受け付ける変数の型がうまく書けなくないですか?
これはどういうこと?
04:38
FooValueCollection が得られれば良いのでは?
Avatar
omochimetaru 09-Jan-18 04:39 AM
for x in Foo.allValues { } みたいに書けるようになっても
04:40
あ〜いやいいのかな
04:41
if x == .bar { ... } if case .baz(false) = x { ... }
こういう感じか。
Avatar
koher 09-Jan-18 04:41 AM
単に全通り列挙がしたいんじゃないのかな?
Avatar
omochimetaru 09-Jan-18 04:42 AM
なんか例えばUIのプルダウンリストを作ったりする時とかがありますね
Avatar
koher 09-Jan-18 04:42 AM
↓とかできたら便利かも?
struct Card : ValueEnumerable { let suit: Suit // Suit : ValueEnumerable let number: Number // Number : ValueEnumerable } Card.allValues
(edited)
Avatar
omochimetaru 09-Jan-18 04:43 AM
それってallValuesの型はなんですか?
Avatar
koher 09-Jan-18 04:43 AM
[Card]
Avatar
omochimetaru 09-Jan-18 04:43 AM
あ〜組み合わせ全列挙ってことか
Avatar
koher 09-Jan-18 04:43 AM
正確には Card.ValueCollection
Avatar
tarunon 09-Jan-18 04:44 AM
allValuesが欲しい場面は結構あって、それは必ずしもenumとは限らないのは確かに
Avatar
omochimetaru 09-Jan-18 04:44 AM
Suit x Number が全部取れると
Avatar
tarunon 09-Jan-18 04:44 AM
組み合わせ列挙とかほしい場面ありますね
Avatar
koher 09-Jan-18 04:45 AM
書いてあった。
To limit our scope, we are primarily interested in simple enums—those without any associated values—although we would also like to allow more complicated enums and structs to manually participate in this mechanism.
Avatar
omochimetaru 09-Jan-18 04:46 AM
ほんとだ。
04:46
まあこういうのっていきなり一般論ぶちあげると議論が発散するからトピックしぼった提案から投げるパターン多いですよね
Avatar
koher 09-Jan-18 04:48 AM
これって前の Int に精度を明示すべきかどうかみたいな話とも関係してるんじゃないかなぁ。 IntValueEnumerable であってほしくないけど(概念としての整数は無限の要素を持つので) UInt8ValueEnumerable であってほしい。同様に考えると Int32UInt32ValueEnumerable であってほしいけど、 Int を associated value に持つ enumValueEnumerable であってほしいわけじゃなくて、 IntInt32 の使い分けはやっぱり必要な気がする。
04:49
トピックしぼった提案から投げるパターン多い
Never の bottom 化早く・・・
Avatar
omochimetaru 09-Jan-18 04:50 AM
おお、たしかに精度無しIntと精度有りIntはそういう違いがあるのか!
04:51
まあ「そのコンパイル時のビット数での要素数になる」って実装もありそうだけど。
Avatar
Kishikawa Katsumi 09-Jan-18 04:51 AM
無限を扱うのは特殊ケースだからそのための特別なものがあればいいと思います。Int = Int64にするのが妥当なところじゃないですかね。
04:51
一貫性を考えるならInt無くしてもいい。
04:52
無限の数というのをIntを含むInt8 〜Int64のファミリーとするのは無理がありますね。 (edited)
Avatar
koher 09-Jan-18 04:52 AM
うーん、僕は allValues ができる Int64 とできない Int を区別しておきたいですねぇ。
04:53
Int64 だと countInt で表せないという話は別として)
Avatar
Kishikawa Katsumi 09-Jan-18 04:55 AM
どうやってもメモリとか何らかの限界はあるわけで、大きなものが必要ならInt64、Int128, Int256でよくて、そうじゃない純粋に整数の性質を表したIntというのは使うところほとんどないと思います。 (edited)
05:00
いや違うかな。書いてて揺らいできた。
Avatar
koher 09-Jan-18 05:01 AM
うーん、好みの問題かもしれませんが、僕はコードとして単に整数を意図しているのか、それとも精度が重要な意味を持つのかを区別したいですね。単に整数を使いたいときに Int32Int64 かの選択が揺らぐようなのをなくしたいです。
Avatar
Kishikawa Katsumi 09-Jan-18 05:01 AM
単に整数を使いたいときに Int32 か Int64 かの選択が揺らぐようなのをなくしたい
05:02
^ これは下は問題にならないわけですよね。どっち使っても収まるのであればどっちでもいいので。で上はやっぱり限界はどこかにある以上、決まってないと使いづらいですね。外への入出力にも使えないし。
05:03
とさっき書いたときまではこういう意見でした。
Avatar
koher 09-Jan-18 05:03 AM
外への入出力を伴うときに、明示的に Int32 等に変換して使いたいイメージですね。
05:03
あと、 Int にはビット演算とかオーバーフローとかもしたくないです。
Avatar
Kishikawa Katsumi 09-Jan-18 05:03 AM
ただ文字列とかは長さの限界を意識することはほとんどないので、もう少し性能が上がったらそれでもいいのかもしれないとも思います。
05:06
確認なんですけどInt64ないしはInt128だけしかなかったら良いと思いますか?
05:06
単に整数を使いたいときに Int32 か Int64 かの選択が揺らぐようなのをなくしたいというのは私はそれでいいと思っています。
05:07
無限の大きさを持つ数というのは別の問題が出てくるはず。
Avatar
koher 09-Jan-18 05:07 AM
Int64ないしはInt128だけ
良いと思わないです。選択のゆらぎの問題は確かにそれで防げますが、それは例が十分じゃなかったです。
(edited)
05:08
DB に保存するエンティティを考えると難しいですね。さすがに「文字列とかは長さの限界を意識することはほとんどない」としても整数でそれをやるのは辛いでしょうし。
05:10
DBの入出力は IntXX でやって、アプリ用に Int を使った型に変換するのか、それともエンティティレベルで Int にして、 DB に保存するときにエラーにしてしまうのか。
Avatar
Kishikawa Katsumi 09-Jan-18 05:11 AM
私はIntみたいなプリミティブなものはそれでしょうがないと思います。無限の数は何らかのデータ構造の型でやれば良いのではないでしょうか。
Avatar
koher 09-Jan-18 05:11 AM
Swift の Int に Java の BigInteger とか Ruby の整数のような無限精度になってほしいわけではないですが、コードの書き手が単なる整数を意図しているのかそうではないのかを型として区別しておきたいという感じですね。
Avatar
Kishikawa Katsumi 09-Jan-18 05:14 AM
十分に小さいから32でも64でもいい、32では入らないけど64あれば十分、それ以上という以外の意図で何か重要なことがありますか?
Avatar
koher 09-Jan-18 05:14 AM
たとえば、 UInt8 だとオーバーフローを利用した計算とかもよくやると思うんですけど、 Int32 ではそれは OK だけど Int ではやりたくないです。そこは明示的に Int32 に変換してから処理したいです。
Avatar
Kishikawa Katsumi 09-Jan-18 05:15 AM
それはおっしゃる通りInt32を使うべきだと思います。
05:16
私は最初は論点はIntが実行環境によって変わることを問題にしていたと思っていて、そこは私も同意です。
Avatar
koher 09-Jan-18 05:17 AM
Int が実行環境によって精度が変わるかどうかは別として、 Int32Int64 より strict な型がほしいという感じですね。
Avatar
Kishikawa Katsumi 09-Jan-18 05:17 AM
なるほど。そこじゃないですか。
Avatar
koher 09-Jan-18 05:17 AM
たとえ Int が 32 bit に固定されていたとしても、 Int に対してオーバーフローを利用した演算はしたくないです。
05:18
感覚的なもので具体的なメリットを挙げづらいですが、そこを区別していないことによって被るデメリットがある気がしています。
Avatar
tarunon 09-Jan-18 05:18 AM
Intが無限長で有限長を使いたいならInt32然りInt64を使う、というのが個人的には一番しっくり来る
05:19
効率の良いプログラムを書きたいなら長さを指定して考えよう、という世界観
Avatar
Kishikawa Katsumi 09-Jan-18 05:19 AM
IntがBigIntのような名前ならいいと思います。
Avatar
koher 09-Jan-18 05:19 AM
@tarunon うーん、そこは僕は違ってて、 Int が現実的に 32bit や 64bit なのには不満はないです。無限精度にはなってほしくない。
05:21
乏しいデメリットですが、さっきの ValueEnumerable の例で言えば
func combination<T: ValueEnumerable, U: ValueEnumerable>(_ a: T.Type, _ b: U.Type) -> [(T, U)]
みたいな関数があったときに
05:21
UInt8Int32Int64ValueEnumerable だけど Int は違ったら
05:22
combination(Int, Bool) みたいなのを防げます。
05:23
でも、 combination(UInt8, Bool) はやりたいですし、 combination(Int32, Bool) も同様に認められるべきだと思います。
Avatar
Kishikawa Katsumi 09-Jan-18 05:24 AM
その例でも私はやっぱりIntをIntファミリから外してBigIntなりの別の型の方がいい気がしますが、それでは問題がありますか? (edited)
Avatar
koher 09-Jan-18 05:26 AM
僕は IntBigInt (無限精度)になってほしいわけではなくて、今のままであってほしいと思います。
05:26
そして、コード中のほとんどの Int は単に整数であってほしいだけだと思うので、基本的には制限された Int を使って
05:26
Int32 特有の操作をするときだけ明示的に Int32 に変換して使えたらいいんじゃないかと思います。
Avatar
d_date 09-Jan-18 07:06 AM
整数としての性質を使いたいだけなら protocol の BinaryInteger 使えばよい、という話ではない? (edited)
Avatar
koher 09-Jan-18 07:11 AM
Int は最もよく利用する型なのでパフォーマンスも求められると思います。 BinaryInteger として existential で扱うのは許容できないかと。たとえば、 countInt を返しますが、これは整数を表していると思います。しかし、これが BinaryInteger になるのは許容できないのではないかと。
Avatar
Kishikawa Katsumi 09-Jan-18 07:12 AM
^ 意見が一致してる気がしますね。何が違うんだろう。
Avatar
koher 09-Jan-18 07:12 AM
僕は今の Swift の仕様に概ね満足しているのでいいのですが、 IntUInt~ が使えるのとかは違和感を感じますね。
Avatar
d_date 09-Jan-18 07:12 AM
しっくりきた
Avatar
koher 09-Jan-18 07:13 AM
1> let n: UInt = 0 n: UInt = 0 2> ~n $R0: UInt = 18446744073709551615
07:13
↑これはできなくていいんじゃないかと思います。
07:13
これがやりたいなら、
3> ~(UInt64(n)) $R1: UInt64 = 18446744073709551615
とすべきかと。
07:14
@Kishikawa Katsumi さんと僕の意見の違いは、 @Kishikawa Katsumi さんはそもそも Int のビット数を固定しなかったのが良くなかったという意見なのに対して、僕はそれでよかったと思ってるところでしょうか。そして、その裏には、 Int は整数だからという気持ちがあります。
Avatar
Kishikawa Katsumi 09-Jan-18 07:15 AM
あと私はIntはInt32かInt64だと思っているところでしょうね。
Avatar
koher 09-Jan-18 07:16 AM
Int のビット数が固定されないことで、↑のようなビット演算が良くない行為となり、明示的な変換が求められます。ただ、もう少し踏み込んで Int には ~&+ 等はなくてよかったと思います。
Avatar
Kishikawa Katsumi 09-Jan-18 07:16 AM
上の例は私はIntはInt64なので別になんの問題もないように見えています。
Avatar
koher 09-Jan-18 07:23 AM
僕の中では Int はほぼ最大値を気にしなくてよい整数なんですよね。 BigInteger が無限精度だと言っても実際には無限ではなくて、↓のような計算をすると精度が足りません。
$ irb irb(main):001:0> 2 ** (2 ** (2 ** (2 ** (2 ** 2)))) (irb):1: warning: in a**b, b may be too big => Infinity
(edited)
Avatar
omochimetaru 09-Jan-18 07:23 AM
え、マジすか?
Avatar
koher 09-Jan-18 07:24 AM
結局どこかには限界があって、通常の演算では 64 ビットだろうがオーバーフローすることはないですし、程度問題だと思います。
Avatar
Kishikawa Katsumi 09-Jan-18 07:25 AM
実際には無限ではないという方が普通に感じるので、 Int はほぼ無限精度整数というのがわからないですね。それは特殊用途ではないですか?
Avatar
koher 09-Jan-18 07:27 AM
「気にしなくてよい」はウソかもですね。 (edited)
07:27
本当は逆で、 BigInteger で何であれ気にしないといけない、かもしれません。 (edited)
07:28
ただ、 99% くらいの用途では問題にならないので、 Int だろうが BigInteger だろうがあまり関係なくどちらも整数と思えるという感じです。
07:29
@omochimetaru irb とか python の REPL で(一つ減らして) 2 ** (2 ** (2 ** (2 ** 2))) と入力すると楽しいことになります。
Avatar
omochimetaru 09-Jan-18 07:31 AM
irb(main):012:0> a.class => Bignum irb(main):013:0> a = 2 ** a (irb):13: warning: in a**b, b may be too big => Infinity irb(main):014:0> a.class => Float
07:31
ほんとだ。まあその前の段階で死ぬほど桁数がでかいから やったらメモリ食いつぶして死ぬのかな
Avatar
koher 09-Jan-18 07:33 AM
宇宙のすべての物質をつかってメモリ作っても全然足りないと思う。 < 2 ** (2 ** (2 ** (2 ** (2 ** 2)))) (edited)
Avatar
omochimetaru 09-Jan-18 07:35 AM
irb(main):035:0> a.to_s.length => 19729
07:35
2^65535はほぼ2万桁あった
07:36
BignumじゃなくてBigDecimalでも試したけど同じ結果になりました・・・
Avatar
koher 09-Jan-18 07:37 AM
観測可能な宇宙の原子総数が 10^80 個程度なのでまったく足りない。
07:38
2^65535 を表すのが、じゃなくて 2^(2^65535) を表すのが
Avatar
tarunon 09-Jan-18 07:38 AM
巨大数の中だとまだ小さい気がする
Avatar
koher 09-Jan-18 07:39 AM
ですね。僕が言いたかったのは、一見できそうな演算でも簡単に BigInteger の限界を突破するということです。
Avatar
sonson 09-Jan-18 11:22 AM
RSA暗号とかも、すぐにぶっ飛びますよ 何も考えずに実装すると 実際にはうまくやりくりする方法がありますが
Avatar
koher 10-Jan-18 01:40 AM
@sonson そういうのは BigInteger が必要そうですねぇ。
Avatar
sonson 10-Jan-18 01:51 AM
実際には,対数上で分解してやるとかの方法でやってたはず・・・・
Avatar
koher 10-Jan-18 02:02 AM
対数上で因数分解なんかできるんですか? log mn = log m + log n を利用してとか?
Avatar
sonson 10-Jan-18 02:10 AM
RSAで使われる離散対数の対象となる数は,factorizeできるので,それで確か,桁あふれを防ぐっていうのを自分で実装したことがある
👀 2
02:10
RSAの基本原理は,以下の数式 (平文)^E mod N = (暗号文) (edited)
02:13
このとき,A * B mod C = ((A mod C ) * (B mod C) ) mod C が成り立つので・・・・みたいな
02:13
Swiftと関係なくてごめん
02:15
これで最後・・・この辺の基本原理は,結城さんの暗号技術入門を読むといいです.あと,RSA暗号の数学的な証明は,ネットにいっぱい転がっています.ただ.証明おっかけるの大変ですが・・・・.
👀 1
👍 1
Avatar
sonson 10-Jan-18 02:40 AM
気にすんなと言われたので加速. 離散対数の基数を計算するのは(つまり平文を計算する),計算時間的に不可能. しかし,EとNをうまく設定してあげると, (平文)^E mod N = (暗号文) (暗号文)^D mod N = (平文) が成立します. このEが公開鍵で,Dが秘密鍵です. NとEから,Dを推定することは,計算時間的に不可能です. しかし,Nは,実は素数pとqの積から計算されており,そのNを作る二つの素数pとqが逆算されてしまうと, Dが,NとEから計算されてしまいます. 量子コンピュータがRSAの根底を揺るがすと言われるのは,量子コンピュータNの素因数pとqを実時間内で計算できる可能性を秘めているからです. もしそうなると,RSA暗号は,暗号文と鍵を一緒に送っていることになってしまうのです. (edited)
02:47
余談 過去,debianのOpenSSLが生成するpとqがshortくらいのサイズで計算するバグが発生. サイズが小さい整数だと,brute forthで,素因数分解できてしまいます. このため,秘密鍵が一瞬で計算できてしまい,どえらいセキュリティ問題が発生したことがあります.
Avatar
Biacco42 10-Jan-18 02:49 AM
楕円関数だと量子コンピュータでの解読ができるかはわからないからマシみたいな話は聞くものの全然わかってない…
Avatar
omochimetaru 10-Jan-18 02:50 AM
昔勉強する機会があったけど、pとqから mod (p * q) 上で 平文と暗号がいったりきたりするEとDを構築するところがいまいち直感的に納得できなかった
Avatar
sonson 10-Jan-18 02:50 AM
離散対数は,環なので,それを使う.
Avatar
omochimetaru 10-Jan-18 02:50 AM
「素数pとqを決めればうまい手順でそのような特性をもつEとDが構成できる」って天下り的になった
Avatar
tarunon 10-Jan-18 02:51 AM
離散対数は,環なので,それを使う.
一番分かりやすかった
Avatar
sonson 10-Jan-18 02:51 AM
それは,離散対数と,フェルマーの小定理から,導かれる.
02:51
俺も,あんまわかってないけど
02:51
いま証明しろと言われてもできないw
Avatar
tarunon 10-Jan-18 02:52 AM
量子コンピューター以降は量子コンピューター以外の暗号は破壊されました、とか普通に有り得そうだなーとか想像してる
Avatar
sonson 10-Jan-18 02:53 AM
Etheriumとかも楕円暗号ベースだし,そっちに移って行くかもね でも,基本は離散対数なので,おんなじなんじゃねーとか小並感的におもっている.
Avatar
omochimetaru 10-Jan-18 02:53 AM
## !!注意事項!! 本記事は、国内の量子情報の市販本を読んで、私なりに理解した情報を、敢えて専門書には書いていない用語も使ったプローチで解説を試みています。正確ではない記述もあり、ご批判はあるとは思います。その点を差し引いて、お読...
Avatar
koher 10-Jan-18 02:53 AM
@omochimetaru
「素数pとqを決めればうまい手順でそのような特性をもつEとDが構成できる」って天下り的になった
同じく。大学で RSA 習って計算もしたはずだけど↑以外忘れてしまった。
Avatar
omochimetaru 10-Jan-18 02:54 AM
とりあえずこれよんでqbit増えるまではセーフやなって最近思った
Avatar
sonson 10-Jan-18 02:54 AM
あと,量子コンピュータは,基本アナログコンピュータなので,統計的にしか結果がでない.
02:55
しもた・・・仕事せんと
Avatar
tarunon 10-Jan-18 02:55 AM
平文よりも導出しやすいニセの平文を積んだ暗号が、量子コンピューター対策にメジャーになる世界観
02:55
状態として平文よりも安定した状態があればそっちが導出されるからーみたいな
Avatar
omochimetaru 10-Jan-18 02:57 AM
たまに数学の話題に転がる事多いし #math 作ってみました。
Avatar
koher 11-Jan-18 02:32 AM
AnyIteratorSequence なのってなんでですか? https://developer.apple.com/documentation/swift/anyiterator
Conforms To IteratorProtocol, Sequence
(edited)
Avatar
omochimetaru 11-Jan-18 02:33 AM
サボれるようにじゃないですか?
02:33
for x in (AnyIterator { hoge() }) {}
これができたら楽
Avatar
koher 11-Jan-18 02:35 AM
↓まったく Sequence としての責務を果たせてない気が。
let i = AnyIterator([2, 3, 5].makeIterator()) let i2 = i.makeIterator() print(i.next()) // 2 print(i2.next()) // 3 let i3 = i.makeIterator() print(i3.next()) // 5
Avatar
t.ae 11-Jan-18 02:35 AM
sequenceでちゃんとやりたいならAnySequence { AnyIterator { hoge() } }になるのかな
Avatar
koher 11-Jan-18 02:35 AM
@omochimetaru それだったら IteratorProtocol : Sequence もほしくならない?
Avatar
omochimetaru 11-Jan-18 02:36 AM
@koher Sequenceは実は1回きりの列挙しか保証しない
Avatar
koher 11-Jan-18 02:37 AM
@omochimetaru それだと SequenceIteratorProtocol の責務が同じにならない?
Avatar
omochimetaru 11-Jan-18 02:37 AM
責務がおなじになるかは次のレベルの議論なのでいったんおいといて
02:37
のところにそうかいてある
02:38
だから、「責務を果たせていない」は、↑の例だけでは、主張できてないと考えます。
02:38
(他になにかおかしいことがあるかもしれないけど、少なくともその例はセーフ)
02:40
struct Countdown: Sequence, IteratorProtocol { var count: Int mutating func next() -> Int? { if count == 0 { return nil } else { defer { count -= 1 } return count } } }
02:40
↑こうやると、 makeIterator が self の return が自動実装される、とか、そういう話も。
Avatar
koher 11-Jan-18 02:40 AM
うーん、そうなのか。そうすると IteratorProtocol との役割分担がよくわからない・・・。
Avatar
t.ae 11-Jan-18 02:40 AM
extension Array { /// Sequence of all sub sequences of specified `length`. public func subSequences(of length: Int) -> SubSequenceSequence<Element> { return SubSequenceSequence(array: self, length: length) }
みたいなのを書いてたんですがSubSequenceIteratorをSequenceにしてそれを返すのも良いのか。
02:42
でもIteratorを返すと複数回呼んだ時に使用中のが返ってきたりする可能性も読み取れるような。 でもSequecne自体も複数回走査が保証されてないなら……
Avatar
omochimetaru 11-Jan-18 02:43 AM
next() が mutating func で makeIterator は nonmutating func って違いはあるけど うーん。
Avatar
t.ae 11-Jan-18 02:47 AM
@koher
それだと Sequence と IteratorProtocol の責務が同じにならない?
Arrayの場合で考えると走査の状態を保持する外部のオブジェクトを生み出すことができるのがSequenceって言えそうですね。 一般のSequenceについては状態をどうするかは不定なのでAnyIteratorのように自身を返すようになってても良いと。
Avatar
koher 11-Jan-18 02:49 AM
SequencemakeIterator で消費されることがありなら、
extension IteratorProtocol { func makeIterator() -> Self { return self } }
的な実装が可能で、すべての IteratorProtocol の実装は Sequence として振る舞えることになる。
Avatar
t.ae 11-Jan-18 03:00 AM
SequenceとIteratorProtocolを同時実装したらmakeIteratorは自動実装されるらしい https://developer.apple.com/documentation/swift/sequence#2849767 (edited)
03:01
@koher が言ってるのはこれを更に進めてIteratorProtocolがSequenceとして振る舞えていいんじゃないかってことですよね
Avatar
koher 11-Jan-18 03:02 AM
はい。ただ、 Swift の仕様で相互に参照するプロトコルが作れるか自信がないです。
Avatar
tarunon 11-Jan-18 03:02 AM
「任意のIteratorをSequenceとして扱える」というのと「全てのIteratorはSequenceである」は大分違う
Avatar
omochimetaru 11-Jan-18 03:02 AM
SequenceとIteratorProtocolを同時実装したらmakeIteratorは自動実装されるらしい
@t.ae#5802 うん、11:37に書いた。
Avatar
tarunon 11-Jan-18 03:02 AM
後者はちょっと乱暴かなぁ
Avatar
t.ae 11-Jan-18 03:03 AM
先にかかれてましたね。
Avatar
t.ae 11-Jan-18 03:10 AM
protocol MySequence { associatedtype Iterator: MyIterator func makeIterator() -> Iterator } protocol MyIterator: MySequence { associatedtype Element func next() -> Element? } extension MyIterator { func makeIterator() -> Self { return self } }
MyPlayground.playground:3:20: Type may not reference itself as a requirement 実装都合な気もしてきた
Avatar
koher 11-Jan-18 03:11 AM
@tarunon IteratorProtocolSequence でないけど AnyIteratorSequence である理由はなんでしょうか?
Avatar
tarunon 11-Jan-18 03:12 AM
手抜きとしか
03:12
なんかSwiftコアメンバーは暗黙的な変換が大好きなように見える (edited)
Avatar
omochimetaru 11-Jan-18 03:12 AM
Swiftコアメンバーは暗黙的な変換が大好きなように見える
ww
Avatar
koher 11-Jan-18 03:12 AM
@t.ae
実装都合な気もしてきた
むー、単に実装できないからそうなってるだけなのか。
03:13
それなら、それはそれで理解はできる。
Avatar
tarunon 11-Jan-18 04:06 AM
そもそもあるProtocolと別のProtocolを相互参照するなら一本化するべきなのでは
04:06
分ける意味あんまないですよね
Avatar
omochimetaru 11-Jan-18 04:09 AM
IteratorProtocol is Sequence と Seuqnece が makeIterator で IteratorProtocol を作れる のは微妙に違うから一本化はできない
04:09
IteratorProtocol is Sequence かつ Sequence is IteratorProtocol になるんだったら一本化できるけど。
Avatar
tarunon 11-Jan-18 04:11 AM
いやできるっしょ
04:11
あれ
Avatar
omochimetaru 11-Jan-18 04:11 AM
Sequence 一般が 複数回イテレーションできる事を保証していないだけで、
Avatar
tarunon 11-Jan-18 04:12 AM
Recursive ConstraintはSwift4だとまだか?
Avatar
omochimetaru 11-Jan-18 04:12 AM
複数回イテレーションしても一貫した結果がえられるSequenceを実装することが禁止されてるわけじゃないから
04:12
そういうのを実装する場合には makeIterator で、 Sequence から 別のオブジェクトとしてのIterator を生成する事に意味がある
Avatar
tarunon 11-Jan-18 04:13 AM
いや別に、Iterator = Selfである必要はないだけで
04:15
Elementの型さえ一致していればその系も表現出来るのだから、
protocol MySequence { associatedtype Element associatedtype Iterator: MySequence where Iterator.Element == Element func makeIterator() -> Iterator func next() -> Element? }
こういう風にできると思う
04:15
てか、Recursive Constraint来てたら、さっきのMySequence/MyIteratorもコンパイル通ると思ったけど
04:15
あーーー
04:16
そっか、Sequenceがnext持ってるのは変だわ、たしかに
Avatar
omochimetaru 11-Jan-18 04:16 AM
nextはmutating funcだね
04:17
うん、nextとmakeIteratorを交互に呼んだ場合に振る舞いが自明でない 1回キリのイテレーションしか保証はされてないから一般には破綻しないけど、 なんどもイテレーションできるSequenceを実装したときに謎になる
Avatar
tarunon 11-Jan-18 04:18 AM
@t.ae Swift4.1ならコンパイル通りましたね
04:18
MySequence/MyIterator
Avatar
t.ae 11-Jan-18 04:25 AM
なるほど。
Avatar
koher 11-Jan-18 04:25 AM
お、じゃあ AnyIteratorSequence なのに IteratorProtocolSequence じゃない理由がない?
Avatar
tarunon 11-Jan-18 04:26 AM
AnyIteratorがSequenceなのが変だと思うけど
Avatar
t.ae 11-Jan-18 05:05 AM
といってSequenceのほうにメソッドが色々生えてるのでIteratorだと使いにくい。 AnySequenceにinit追加したら良いんじゃと思うんですがどうでしょう?
extension AnySequence { init(iterator: @escaping ()->Element?) { self.init { return AnyIterator(iterator) } } }
Avatar
koher 11-Jan-18 05:54 AM
AnyIteratorがSequenceなのが変だと思うけど
僕もこちら側の意見です。 Sequence がイテレータ経由で consume されるのも微妙な気が。
Avatar
koher 11-Jan-18 06:04 AM
for で回したいんだったら for inT: IteratorProtocol を許容するようにした方がシンプルな気もするけどなぁ。
Avatar
t.ae 11-Jan-18 06:17 AM
zipとかもあるんでfor in だけできても微妙な気が
Avatar
koher 11-Jan-18 06:41 AM
あー、 map とかもできるのかと思ったら単に AnyIteratorSequence だからできるだけだった。
06:42
うーん、 AnyItearator については使い捨てで操作したいこともあるし、かといって AnyIterator AnySequence で包むのはオーバーヘッドがあるからしかたないのかなぁ。 (edited)
Avatar
t.ae 11-Jan-18 06:43 AM
AnySequenceで包むのは〜の誤りですか?
Avatar
koher 11-Jan-18 06:43 AM
ああ、そう。
Avatar
t.ae 11-Jan-18 06:51 AM
06:51
何をもって分かれてるんだろう
Avatar
omochimetaru 11-Jan-18 06:54 AM
Zip2Iteratorは直接構築しなくて
06:54
Zip2Sequenceが内部で実装としてもってる型なんじゃない?
Avatar
t.ae 11-Jan-18 06:55 AM
https://github.com/apple/swift/blob/9361a6b66f6f8351e89c090f604d7e1f42e2a045/stdlib/public/core/Zip.swift#L148-L153 SequenceではSequenceで持ってIteratorではIteratorで持つというのは分かるんですが
swift - The Swift Programming Language
06:57
僕が引っかかったのはzipのイテレータだとSequenceとして不適当な場合があるのかってことですね
Avatar
omochimetaru 11-Jan-18 06:59 AM
makeIterator() するたびに最初から列挙し直すためでは?
06:59
正しく動くのは zipされるSequence2つが、再列挙に対応している場合に限るけど。
07:00
ああそうか、IndexingIterator が Sequence でもいいのは、
Avatar
t.ae 11-Jan-18 07:00 AM
そうですね。その制限があるんでZip2IteratorがSequenceじゃない必要がないんじゃないかと
Avatar
omochimetaru 11-Jan-18 07:00 AM
IndexableなCollectionから生成される時点で
07:00
再列挙が常に正しいからだ。 (edited)
07:01
その制限があるからZip2IteratorがSequenceだとおかしくならない?makeIteratorでselfを返すと再列挙できない (edited)
Avatar
t.ae 11-Jan-18 07:02 AM
let a = [0, 1, 2] var i1: IndexingIterator<[Int]> = a.makeIterator() print(i1.next()) // 0 var i2: IndexingIterator<[Int]> = i1.makeIterator() print(i2.next()) // 1
再列挙してないみたいです
(edited)
Avatar
omochimetaru 11-Jan-18 07:03 AM
ほんとだ。
07:03
じゃあこれもAnyIteratorと同じで楽にできるようになってるだけか・・・ (edited)
Avatar
t.ae 11-Jan-18 07:03 AM
その制限があるからZip2IteratorがSequenceだとおかしくならない?makeIteratorでselfを返すと再列挙できない
そもそも再列挙できなくてもいいのがSequenceという話では
Avatar
omochimetaru 11-Jan-18 07:03 AM
それでいいならZip2IteratorもSequenceでも良いわなあ
07:03
いや
07:03
できなくてもいいじゃなくて
07:03
ソースが対応しているならできたほうがいいってこと
07:04
できなくてもいいけど、できるならできたほうがより良い
Avatar
t.ae 11-Jan-18 07:04 AM
それはそうですね。
Avatar
omochimetaru 11-Jan-18 07:04 AM
zipの場合は、ZipSequenceで抱えてるソース1とソース2が再列挙できるSequenceなら、最初からやりなおせたらいい
07:04
でもIndexedIteratorでよくわかんなくなったわ。
Avatar
t.ae 11-Jan-18 07:10 AM
お、
07:10
let a = [0, 1, 2] var i1: IndexingIterator<[Int]> = a.makeIterator() print(i1.next()) // 0 var i2: IndexingIterator<[Int]> = i1.makeIterator() print(i2.next()) // 1 print(i1.next()) // 1
分岐はしているみたい
07:11
IndexingIteratormakeIteratorで途中状態を考慮したIteratorが帰ってくるというのは別に悪くないようにも思えますねぇ
Avatar
omochimetaru 11-Jan-18 07:15 AM
イテレーターっていうのがそもそもそういう概念の事では
07:16
mutating func next() からもわかるとおり、場所を保持する。
07:16
ただsequenceとしてアクセスして.makeIteratorしたときの振る舞いは自明でない・・・
Avatar
koher 11-Jan-18 07:20 AM
IndexingIterator は意図がよくわかんないけど、
07:21
Zip2IteratorZipSequence 経由で生成するから、逆に Iterator から Sequence を作りたいユースケースがないんじゃない?
Avatar
omochimetaru 11-Jan-18 07:22 AM
IndexingIteratorもCollectionから作るし自作はできないっぽい? initがみえない
Avatar
koher 11-Jan-18 07:22 AM
AnyIterator の場合は Sequence を作りたくなるユースケースが想定されて、しかも AnySequence でラップするには無視できないオーバーヘッドがあって仕方なく Sequence になってるのかと。
07:22
IndexingIterator はわかんない。
🤔 1
Avatar
t.ae 11-Jan-18 07:29 AM
そこのオーバーヘッドってそんな大きいんですかね
Avatar
omochimetaru 11-Jan-18 07:30 AM
まあmakeIteratorを呼び出すのは一回だけで、その後はIteratorオブジェクトしか関与しないから
07:30
イテレーションするようなシナリオにおいては最初の1回だけってのは小さいよね
07:30
オブジェクトの生成は生じるし確実に無駄ではあるけど。
Avatar
koher 11-Jan-18 07:32 AM
うーん、イテレーション自体を考えたら無視できるってのはそうかもしれないけど、無駄にヒープにアロケートするのは微妙ではあるよね。
Avatar
omochimetaru 11-Jan-18 07:33 AM
そうですね。
Avatar
koher 11-Jan-18 07:33 AM
API上の利便性でこうなってるなら、 AnySequence で包んでから使う方がいいと思うけど。 (edited)
Avatar
omochimetaru 11-Jan-18 07:33 AM
なんか僕の感覚だと初級プログラマが混乱しないようにそうしたにおいがする
07:34
AnySequence で包んでから使う方がいいと思うけど。
同意
07:34
Promiseのthenみを感じる。
Avatar
koher 11-Jan-18 07:34 AM
えー、 IteratorProtocolSequence を混ぜるのは余計混乱するのでは?
Avatar
omochimetaru 11-Jan-18 07:34 AM
混ぜないほうがいいってことです
Avatar
koher 11-Jan-18 07:35 AM
ああ、 AnyIterator の話じゃないのか。
07:36
Sequence は基本的には makeIterator を複数回実行できることを想定しながらも、 consume するものにも使えるというのはまあいい気がしてきた。
Avatar
tarunon 11-Jan-18 10:51 AM
static func initの裏技(by @lovee )、自身の型を返してサブクラス作るとセグフォ出ますね。
10:51
class My { static func `init`(arg: Void) -> My { return MyMy() } } class MyMy: My { } My(arg: ())
(edited)
Avatar
omochimetaru 11-Jan-18 03:18 PM
お~
Avatar
tarunon 12-Jan-18 01:50 AM
protocol initなしでワンチャンあるか?と思ったけど無かった
Avatar
tarunon 17-Jan-18 03:19 AM
@hiragram RxのPrimitiveSequence.flatMapのoverloading、何かしら作業してたかしら
Avatar
hiragram 17-Jan-18 03:19 AM
まだなんも
Avatar
tarunon 17-Jan-18 03:19 AM
スレに書き込みあったから便乗しといた https://github.com/ReactiveX/RxSwift/issues/1206#issuecomment-358182422
⚠️ If you don't have something to report in the following format, it will probably be easier and faster to ask in the slack channel first. ⚠⚠️ Please take you time to fill in the fields below. If...
Avatar
hiragram 17-Jan-18 03:20 AM
+1しといた
Avatar
tarunon 17-Jan-18 03:20 AM
別に+1しろってことではないんだがw
03:20
議論に参加してねということです
Avatar
hiragram 17-Jan-18 03:21 AM
する
Avatar
hiragram 17-Jan-18 03:30 AM
した
Avatar
tarunon 17-Jan-18 03:32 AM
えらい
Avatar
hiragram 17-Jan-18 03:33 AM
I encounter that situation almost every day.
これはちょっと盛った
Avatar
tarunon 17-Jan-18 03:33 AM
正直ワロタ
Avatar
hiragram 17-Jan-18 03:34 AM
いや、でも実際毎日asObservable asCompletableしてるかもしれない
Avatar
tarunon 17-Jan-18 03:34 AM
オレオレflatMap作ってないの
Avatar
hiragram 17-Jan-18 03:34 AM
つくってない
03:35
つくるかあ
Avatar
tarunon 17-Jan-18 03:35 AM
どうせ追加されるから作って損はないと思うし
03:35
追加されなかったら作るの必須だからどっちにしてもやるしかない
Avatar
hiragram 17-Jan-18 03:35 AM
「本家にあるやつなのか、自分で作ったやつなのか」がパッと見でわからなくなるのはなんか嫌なんだよな
Avatar
tarunon 17-Jan-18 03:36 AM
アンスコでもつけとけ
Avatar
hiragram 17-Jan-18 03:36 AM
このオペレータ壊れてるやんけキレたろと思ってキレかけたら自分で作ったやつだったとか
03:36
アンスコはありありのあり
Avatar
tarunon 17-Jan-18 03:36 AM
それか、extension作ればいいんちゃうか
03:36
observable.my.flatMapみたいな
Avatar
hiragram 17-Jan-18 03:37 AM
他に結構な数のオペレータ作ってしまってるからエイヤで移行するのも手間だしこれは my 無くてこっちはあるとかそんなんは地獄っぽいのでアンスコがコスパ良いかなーって感じする
Avatar
tarunon 17-Jan-18 03:46 AM
アンスコならリファクタリングで済むから安いっすね
Avatar
t.ae 19-Jan-18 06:00 AM
3のプロジェクトを4に移行していたらこんなのがでてきました。
let a = [0: true, 1: false] // Error: `filter` is ambiguous // let x = a.filter { $0.value }.sorted(by: { $0.key < $1.key }) // Equivalent let x1 = a.filter { $0.value } let x2 = x1.sorted(by: { $0.key < $1.key})
4からDictionaryfilterが二種類になったみたいで、 分割して書いた場合は優先順位が付くけどsortedが続いた場合は型推論で両方通るのでambiguousになる?みたいです
06:01
こう書くとか
let x = (a.filter { $0.value } as Array).sorted(by: { $0.key < $1.key })
ソートを先にするとかで対応できますがいまいち……
Avatar
tarunon 19-Jan-18 06:01 AM
きびしいw
06:02
prefixで死んだのと同じっぽいですね
06:02
やはり高階型が必要…
Avatar
t.ae 19-Jan-18 06:02 AM
sortedがついた場合も優先順位働かせることはできそうですけど やっぱ中間の型が隠れてるのは良くないとかいう判断なんでしょうかね。 (edited)
Avatar
rintaro 19-Jan-18 06:12 AM
4.1 では通るみたいです。
06:13
型推論のランキング方法が変更されたのかも。
Avatar
t.ae 19-Jan-18 06:14 AM
お、まじですか
Avatar
tarunon 19-Jan-18 06:14 AM
CondConf関係でしょうか
Avatar
rintaro 19-Jan-18 06:15 AM
わからん。 https://bugs.swift.org/browse/SR-6634
Pavel Yaskevich, I wonder if this is related to the ranking changes you made?
とあるので、何かしらの変更があったのは確かみたいです。
Avatar
t.ae 19-Jan-18 06:17 AM
でてきたのがsortedだったのでそのまま書きましたがcountの例のほうがより問題に近かったですね。
Avatar
rintaro 19-Jan-18 06:31 AM
https://bugs.swift.org/browse/SR-1996 そのものっぽいのを見つけました。
06:33
あ、values に対する filter だから違うか。
Avatar
t.ae 19-Jan-18 06:33 AM
ちょっと違いますね というかcountだと通るというよく分からない状態 に
let a = [0: true, 1: false] let xx = a.filter { $0.value }.count
🤔 1
Avatar
rintaro 23-Jan-18 05:51 AM
enum E { case A(Int, String) case B(String, Float) } func foo(e: E) { switch e { case .A(_, let str): // something. fallthrough case .B(let str, _): print(str) } }
これが通るようになるらしいです。 https://github.com/apple/swift/pull/14041/files#diff-3f455e97fae02f7b158f90077919c17fR140
This is the simplest / most-restrictive version of this feature. The previous case that we're falling from must have a superset of the bindings of the case we're falling into and all the to-case bi...
Avatar
tarunon 23-Jan-18 06:26 AM
protocol変数だと死にそうだ
Avatar
rintaro 23-Jan-18 06:46 AM
そのバグは解消されていたような。
Avatar
tarunon 23-Jan-18 06:47 AM
解消されたというか
06:48
セグフォ→コンパイルエラーになりました、だったような
Avatar
rintaro 23-Jan-18 06:49 AM
セグフォ→コンパイルエラー→解消 に最近なったという意味で。
Avatar
tarunon 23-Jan-18 06:49 AM
maji
06:50
1/16の4.1スナップショットはまだだった。
Avatar
rintaro 23-Jan-18 06:51 AM
残念ながら 4.1 には入らないと思います。5.0 待ち。
02:52
Sequenceに辞書順比較入ってるのめっちゃ便利だ
02:52
Data型で使えた。
02:53
いまバイナリ列を順序比較したかった。
Avatar
koher 25-Jan-18 03:15 AM
String< はこれで実装されているわけではない?
This method implements the mathematical notion of lexicographical ordering, which has no connection to Unicode. If you are sorting strings to present to the end user, use String APIs that perform localized comparison.
03:15
↑ "localized comparison" って、ローカライズ環境によって String< の順序変わるの??
Avatar
omochimetaru 25-Jan-18 03:16 AM
a と Aとかじゃないですか?
03:16
キャラクターコード順だと apple banana Apple だけど期待される文字列ソートは apple Apple banana になりそう (edited)
Avatar
koher 25-Jan-18 03:17 AM
ASCII は A が a より早いのでは?
Avatar
omochimetaru 25-Jan-18 03:17 AM
それでもいいです そうじゃなくてw
03:17
AとBの前後順。
Avatar
koher 25-Jan-18 03:17 AM
はい、わかります。
Avatar
omochimetaru 25-Jan-18 03:17 AM
(a|A) < (b|B)
03:18
なんかまえに @norio_nomura さんが文字列のソート順が Linuxだと違うとか
Avatar
koher 25-Jan-18 03:18 AM
いろいろ疑問があるけど、まずそれは Character の順序やんね?
Avatar
omochimetaru 25-Jan-18 03:18 AM
ふんでたな
Avatar
koher 25-Jan-18 03:18 AM
その Character の順序が (a|A) < (b|B) になってたら
03:19
StringlexicographicallyPrecedes もその順になるのでは?
Avatar
omochimetaru 25-Jan-18 03:19 AM
たしかに。この例だとCharacterのSequenceにおいてlexicographicallyだから不適切だ。
03:20
Unicodeって文字列のソート順規定もあった気がする
Avatar
koher 25-Jan-18 03:20 AM
$ swift Welcome to Apple Swift version 4.0.3 (swiftlang-900.0.74.1 clang-900.0.39.2). Type :help for assistance. 1> let a: Character = "a" a: Character = { _representation = smallUTF16 { smallUTF16 = 97 } } 2> let b: Character = "B" b: Character = { _representation = smallUTF16 { smallUTF16 = 66 } } 3> a < b $R0: Bool = false
(edited)
Avatar
omochimetaru 25-Jan-18 03:20 AM
swift - The Swift Programming Language
03:20
マジかw
03:22
var ss = ["apple", "Apple", "banana"] ss.sort() print(ss) // "["Apple", "apple", "banana"]\n" ss.sort { (a, b) in a.lexicographicallyPrecedes(b) } print(ss) // "["Apple", "apple", "banana"]\n"
03:22
↑とりあえずまずはこう
03:23
@_inlineable @_versioned internal static func compare( _ left: _StringGuts, to right: _StringGuts ) -> Int { defer { _fixLifetime(left) } defer { _fixLifetime(right) } #if _runtime(_ObjC) // We only want to perform this optimization on objc runtimes. Elsewhere, // we will make it follow the unicode collation algorithm even for ASCII. // This is consistent with Foundation, but incorrect as defined by Unicode. // // FIXME: String ordering should be consistent across all platforms. if left.isASCII && right.isASCII { let leftASCII = left._unmanagedASCIIView let rightASCII = right._unmanagedASCIIView let result = leftASCII.compareASCII(to: rightASCII) return result } #endif return _compareDeterministicUnicodeCollation( _leftUnsafeStringGutsBitPattern: left.rawBits, _rightUnsafeStringGutsBitPattern: right.rawBits) }
03:23
すごいFIXMEあった
Avatar
koher 25-Jan-18 03:24 AM
www
// FIXME: String ordering should be consistent across all platforms.
Avatar
omochimetaru 25-Jan-18 03:24 AM
これはw
Avatar
koher 25-Jan-18 03:25 AM
あと疑問なんだけど、 Unicode のコードポイントの順序を比較できるのはいいとして、 Character って書記素クラスタだから何によって順序付けされてるの? a < B であることからそもそもコードポイントでないんだろうけど。
Avatar
omochimetaru 25-Jan-18 03:26 AM
そこが、Unicodeで決まってる気がするんですよね
Avatar
koher 25-Jan-18 03:26 AM
書記素クラスタの順序?
Avatar
omochimetaru 25-Jan-18 03:26 AM
そこまではわからないけど
03:26
aとAが仲間だよ、とか、そういうコードポイント以外の情報。
Avatar
koher 25-Jan-18 03:26 AM
そこが Unicode 決まってたら、 Java の String の順序とかぐちゃぐちゃになってそう・・・
Avatar
omochimetaru 25-Jan-18 03:27 AM
とりあえずnon-objcで追ってみよう libicu に帰着しそうだが
03:27
/// Compares two slices of strings with the Unicode Collation Algorithm. @inline(never) // Hide the CF/ICU dependency @effects(readonly) public // @testable static func _compareDeterministicUnicodeCollation(
03:28
Unicode Collation Algorithm というキーワードが出てきた。
03:28
Collationは 「ガ」と「カ+濁点」を正規化したりするやつかな
03:28
どちらも見た目上は1文字のガに見える。 (edited)
Avatar
koher 25-Jan-18 03:29 AM
ん??↑の例、 banana じゃなくて Banana じゃないといけない気が。
03:29
3> ["apple", "Apple", "banana", "Banana"].sorted() $R2: [String] = 4 values { [0] = "Apple" [1] = "Banana" [2] = "apple" [3] = "banana" }
Avatar
omochimetaru 25-Jan-18 03:29 AM
var ss = ["apple", "Apple", "banana", "Banana"] ss.sort() print(ss) // ["Apple", "Banana", "apple", "banana"]\n" ss.sort { (a, b) in a.lexicographicallyPrecedes(b) } print(ss) // ["Apple", "Banana", "apple", "banana"]\n"
03:29
たしかに・・・
03:29
普通に大文字が前だった。
Avatar
koher 25-Jan-18 03:30 AM
どうやっても辞書順無理なのかw
Avatar
omochimetaru 25-Jan-18 03:30 AM
結局辞書にならんのかい
Avatar
koher 25-Jan-18 03:31 AM
そうすると、単純にはコードポイントの順になってそうだけど、書記素クラスタはどうなってるのかな?コードポイントのシーケンスとして lexicographicallyPrecedes 的な?
03:31
/// Compares the strings via the Unicode Collation Algorithm on the root locale. /// Results are the usual string comparison results: /// <0 the left string is less than the right string. /// ==0 the strings are equal according to their collation. /// >0 the left string is greater than the right string. int32_t swift::_swift_stdlib_unicode_compare_utf16_utf16(const uint16_t *LeftString, int32_t LeftLength, const uint16_t *RightString, int32_t RightLength) { // ICU UChar type is platform dependent. In Cygwin, it is defined // as wchar_t which size is 2. It seems that the underlying binary // representation is same with swift utf16 representation. // On Clang 4.0 under a recent Linux, ICU uses the built-in char16_t type. return ucol_strcoll(GetRootCollator(), reinterpret_cast<const UChar *>(LeftString), LeftLength, reinterpret_cast<const UChar *>(RightString), RightLength); }
(edited)
03:33
他にもutf8まじりのオーバーロードとかったけどutf16同士だとここになる ここでSwiftから見ると C 関数の _swift_stdlib_unicode_compare_utf16_utf16 が C++ で実装されてて ucol_strcoll の呼び出しに帰着してる これは外部のlibicuのシンボルじゃないか (edited)
Avatar
koher 25-Jan-18 03:34 AM
4> ["👨‍👩‍👧‍👦", "👨", "👩"].sorted() $R3: [String] = 3 values { [0] = "👨" [1] = "👨‍👩‍👧‍👦" [2] = "👩" }
Avatar
omochimetaru 25-Jan-18 03:34 AM
コメントにroot locale ってあって、 GetRootCollator() とか書いてあるし、設定みたいなものには依存しない気がする
Avatar
koher 25-Jan-18 03:36 AM
👨👩👧👦 (edited)
03:36
Facebook では父母の位置が反転するらしい。ヤバイ。
03:37
↓(👨👩👧👦)をつないでるのに。
U+1F468 U+200D U+1F469 U+200D U+1F467 U+200D U+1F466
(edited)
03:39
ICU comes with a large set of already predefined collators that are suited for specific locales. Most of the ICU locales have a predefined collator. In worst case, the default set of rules, which is equivalent to the UCA ordering, is used.
03:40
ICUはライブラリとしてロケールごとのcollationを規定しているがデフォルトではUCA順序になる(RootLocale?
03:40
Unicode® Technical Standard #10 UNICODE COLLATION ALGORITHM
Avatar
koher 25-Jan-18 03:40 AM
ロケールごとに文字列の順序決まってるって色々ヤバそうな感じがする・・・
Avatar
omochimetaru 25-Jan-18 03:41 AM
そこがよくわかんないですね。
03:41
具体的にJPとENで入れ替わるパターンを知りたいな。
Avatar
koher 25-Jan-18 03:41 AM
ドイツ語とかでÄとか考えたときに、 A の後に入れたいとかあるのかな?
Avatar
omochimetaru 25-Jan-18 03:41 AM
金正日を表記するようの金の文字は前にあるとかかね
03:42
あれはユニコードには無いのかな 北朝鮮の文字コード体系には存在するらしいが
03:42
あ〜
03:42
ありそうですね>Aのポチつき
Avatar
koher 25-Jan-18 03:42 AM
同じ文字を複数言語で使ってる場合に順序が衝突することはありそう。
03:42
日本語の漢字と中国語の漢字で順序を別にしたいとか。
03:43
そもそも漢字の順序って何?って思うけど。
Avatar
omochimetaru 25-Jan-18 03:43 AM
Language Swedish: z < ö German: ö < z Usage German Dictionary: of < öf German Phonebook: öf < of Customizations Upper-First A < a Lower-First a < A
Avatar
koher 25-Jan-18 03:43 AM
ただ、法でも字の順序を決めるとかもありえるかも。
03:43
ヤバw < ↑の例 (edited)
Avatar
omochimetaru 25-Jan-18 03:43 AM
Collation varies according to language and culture: Germans, French and Swedes sort the same characters differently. It may also vary by specific application: even within the same language, dictionaries may sort differently than phonebooks or book indices.
03:44
ドイツ語とフランス語で同じ文字でも違う順番になるし
03:44
同じ言語でもフォンブックとブックインデックスで違う?
Avatar
koher 25-Jan-18 03:44 AM
Locale 情報が static に存在してるのって気持ちわるいんだよなぁ。
Avatar
omochimetaru 25-Jan-18 03:44 AM
なに??
Avatar
koher 25-Jan-18 03:45 AM
ロケールを渡さなくてもデフォルトロケールに基いてソートされるってことでしょ?
Avatar
omochimetaru 25-Jan-18 03:45 AM
電話帳と本の索引で辞書順の並びが変わる言語があるって書いてあるけど何を言ってるかさっぱりわからない・・・
03:46
Language Swedish: z < ö German: ö < z Usage German Dictionary: of < öf German Phonebook: öf < of Customizations Upper-First A < a Lower-First a < A
03:46
German DictionaryとGerman Phonebook の例っぽいけどどういうことなんだ
Avatar
koher 25-Jan-18 03:46 AM
電話帳と本の索引で辞書順の並びが変わる言語がある
ひどいw
03:47
まあ、文字の順序が法で決められてなければ分野によってバラツキがあるまま発展したとかありそう。
Avatar
omochimetaru 25-Jan-18 03:47 AM
あるのかもしれないけどなんで電話帳が違うんだ・・・
03:48
Table 2. Comparison Levels Level Description Examples L1 Base characters role < roles < rule L2 Accents role < rôle < roles L3 Case/Variants role < Role < rôle L4 Punctuation role < “role” < Role Ln Identical role < ro□le < “role”
03:49
Table 4. Context Sensitivity Contractions H < Z, but CH > CZ Expansions OE < Œ < OF Both カー < カア, but キー > キア
03:49
日本語で伸ばし棒の音が前の音のアイウエオで変わるみたいな事かこれ
Avatar
norio_nomura 25-Jan-18 03:49 AM
Avatar
omochimetaru 25-Jan-18 03:49 AM
このドキュメント、読むのしんどすぎてダメだ・・・
03:50
つまりどうなってるのかに辿り着く前にパンクする・・・
03:50
@norio_nomura 以前触れてたやつ、まだOPEN issueなんですね、まあ、コードもFIXMEだったし。
03:51
ObjCの振る舞い全部捨ててICUに統一したらいいのに。
03:51
互換性で爆発するかしら・・・
Avatar
koher 25-Jan-18 03:51 AM
カー < カア, but キー > キア
これ確かに日本語ネイティブだから意識してないけどヤバイな。
Avatar
norio_nomura 25-Jan-18 03:51 AM
ICUに依存しない実装のPRが出てるけど、パフォーマンスが出ないみたい。https://github.com/apple/swift/pull/13877
Avatar
omochimetaru 25-Jan-18 03:52 AM
var ss = ["カア", "カー", "キイ", "キー"] ss.sort() print(ss) // ["カア", "カー", "キイ", "キー"] ss.sort { (a, b) in a.lexicographicallyPrecedes(b) } print(ss) // ["カア", "カー", "キイ", "キー"]
03:52
特に考慮されないモードのようだ。
Avatar
koher 25-Jan-18 03:55 AM
日本生まれの Ruby でもダメだった。
puts "カー" < "カア" # false puts "キー" < "キア" # false
Avatar
omochimetaru 25-Jan-18 03:58 AM
ICUに依存しない実装のPRが出てるけど、パフォーマンスが出ないみたい。https://github.com/apple/swift/pull/13877
なるほど StringNormalization.swiftがたされるんですね
Avatar
norio_nomura 25-Jan-18 04:00 AM
ICUの初期化パラメータを変えて、Darwinの挙動に近くするPRを以前書いたけど「ICUへ依存しない実装へ変えるべき」とか言われてマージしてもらえなかった。 https://github.com/apple/swift/pull/8769
This PR changes to use default collator instead of root collator. http://icu-project.org/apiref/icu4c/ucol_8h.html said about ucol_open()'s locale parameter as: loc The locale containing the requ...
Avatar
tarunon 25-Jan-18 04:01 AM
これパフォーマンス出る実装できるんですか?直感では何も思いつかない
Avatar
omochimetaru 25-Jan-18 04:01 AM
@tarunon ICUと同等のパフォーマンスは出るんじゃ?
04:01
public func _compareStringsPreLoop( selfUTF16: UnsafeBufferPointer<UInt16>, otherUTF16: UnsafeBufferPointer<UInt16> ) -> _Ordering {
04:03
UTF16で見て違いが出るところを見つけて、その場所からこんどはセグメントの始まりまで巻き戻して・・・
04:04
lexicographicalでいける場合はいけるけど、そうじゃない場合に // Pathological case: multi-segment expanders ruin segment-by-segment // processing.
04:04
pathlogical caseとやらが最悪系
Avatar
tarunon 25-Jan-18 04:04 AM
ふむふむ
Avatar
omochimetaru 25-Jan-18 04:05 AM
// NOTE: Multi-segment expanders are (at least up til Unicode 10) always the // beginning of a normalization segment (i.e. they are starters).
04:05
unicode10とか書いてあるしまさに絵文字結合とかが入った世代だろうか
04:06
private func _compareStringsPathological( selfUTF16: UnsafeBufferPointer<UInt16>, otherUTF16: UnsafeBufferPointer<UInt16> ) -> _Ordering { var selfIterator = NormalizedIterator(selfUTF16) return selfIterator.compare(with: NormalizedIterator(otherUTF16) ) }
(edited)
04:06
いろんなファストパスこけた場合の最終汎用系がこれか
04:09
そのIteartorの中で normalizeがされて・・・
internal func _tryNormalize( _ input: UnsafeBufferPointer<UInt16>, into outputBuffer: UnsafeMutableBufferPointer<UInt16> ) -> Int? { var err = __swift_stdlib_U_ZERO_ERROR let count = __swift_stdlib_unorm2_normalize( _Normalization._nfcNormalizer, input.baseAddress._unsafelyUnwrappedUnchecked, numericCast(input.count), outputBuffer.baseAddress._unsafelyUnwrappedUnchecked, numericCast(outputBuffer.count), &err ) guard err.isSuccess else { // The output buffer needs to grow return nil } return numericCast(count) }
04:09
__swift_stdlib_unorm2_normalize まできた。
04:10
あれ
04:10
unorm2_normalize
04:10
の呼び出しに行っちゃった
04:10
これはICUだから
04:10
ICUに依存しない
というわけではない?
04:11
ICU自体は使うけど、ソート順序に関しては依存しないってことかな?
04:11
Unicodeのnormalizeとcollationは違う概念っぽいな
04:13
normalizeのほうが小さい道具なら、ICUに全部任せてたのを一部Swiftで自前で書いたという感じだけど、
04:13
それでパフォーマンスが出てないなら、ロジックが悪いか、SwiftがまだC++に追いつけて無い部分があるのか
04:14
ほとんどのテストが80~90%ぐらいに性能低下しちゃってるんだなあ
Avatar
norio_nomura 25-Jan-18 04:16 AM
あれ?まだ依存してましたか。てっきり依存しない実装かと勘違いしていました。失礼。
Avatar
omochimetaru 25-Jan-18 04:16 AM
collationでの依存はなくなったけどnormalizeでは依存してるという感じに見えます。
04:18
Apple勢同士のPRだとあんまり議論の詳細が書いてないからよくわからんですなあ
Avatar
norio_nomura 25-Jan-18 04:22 AM
ICU依存云々は僕の記憶がどこかで書き換わっていたぽい。 https://github.com/apple/swift/pull/8769#issuecomment-294310129 から引用。
> @dabrahams Sorry, I didn't read the string manifesto. > Hm, it seems that the string manifesto says "Swift string sorting will not be compatible with > Foundation sort order". > Is that correct with that understanding? Yes, non-localized String sorting will not work the same way in Swift as it does in Foundation. We intend to try very hard to keep localized sorting in sync, though.
なんか詳細忘れちゃったな…
This PR changes to use default collator instead of root collator. http://icu-project.org/apiref/icu4c/ucol_8h.html said about ucol_open()'s locale parameter as: loc The locale containing the requ...
04:25
Foundationの挙動はUnicodeに一部従ってないから、SwiftのStringはUnicodeに従った挙動にすべきとString Manifestoでは言っていて、つまりString Manifestoが実装されるとFoundationとStdlibの文字列比較の挙動は違ってくる。とかだったかしら?
Avatar
omochimetaru 25-Jan-18 04:27 AM
ふむふむ
Avatar
norio_nomura 25-Jan-18 05:24 AM
SwiftJPでおもちさんと話してた https://swiftjp.slack.com/archives/C047W3ASS/p1492052507428667
Avatar
omochimetaru 25-Jan-18 05:28 AM
norio_nomura [12:54 PM] ASCIIに関しては一部の記号の扱いがFoundationとUnicodeで違うぽい。 [12:54 PM] で、大文字小文字のどちらが前に?ってのは、Unicodeでも「カスタマイズできるようにするべき」って書かれてる。 http://unicode.org/reports/tr10/#Case_Comparisons (edited)
05:29
そうそう、このやりとりをぼんやりおもいだしていましsた
Avatar
omochimetaru 25-Jan-18 05:44 AM
Recently, I proposed the idea of adding the ability to implement the "class cluster" pattern from Cocoa (Touch) in Swift. However, as we discussed it and came up with different approaches, it evolved into a functionality that I believe is far more beneficial to Swift, and subsequently should be the focus of its own proposal. So here is the improved (pre-)proposal: # Factory Initializers The "factory" pattern is common in many languages, including Objective-C. Essentially, instead of initializi...
05:44
factory init のプロポザル出てた
05:45
ん??12月ってこれ3年前の12月だ!
Avatar
t.ae 25-Jan-18 05:45 AM
’分かりにくいですよね
Avatar
omochimetaru 25-Jan-18 05:45 AM
右のところみないときづけんな。
Avatar
koher 25-Jan-18 06:02 AM
右端じゃなくて、枠内の日付表示の Dec '15 の 15 も 2015 年みたい。
Avatar
omochimetaru 25-Jan-18 06:02 AM
!!!!
06:02
15日かと思ってたwwww
Avatar
t.ae 25-Jan-18 06:02 AM
’分かりにくいですよね
というコメント自体が分かりにくかったか
Avatar
Biacco42 25-Jan-18 06:02 AM
www
06:03
そうなのかこれw
Avatar
omochimetaru 25-Jan-18 06:03 AM
@t.ae きづかねえ→「'」
06:03
ジャップ芸をしてしまった・・・
Avatar
tarunon 25-Jan-18 06:03 AM
カーソルを日付に合わせてぢっとしていると、真の日付が表示されるぞ
Avatar
omochimetaru 25-Jan-18 06:04 AM
@tarunon ほんとだ。裏技だ。
Avatar
Biacco42 25-Jan-18 06:04 AM
超能力者向けか?
Avatar
omochimetaru 25-Jan-18 06:04 AM
クリックでもいいのか。
06:04
まあでもフォーラムになってめっちゃよくなったわ
Avatar
rintaro 25-Jan-18 06:04 AM
FWIW, even in Swift2, factory initializer is possible. I've post a gist here: https://gist.github.com/rintaro/9eadc2720ac8be6a7898 It's pretty hackish though 🙂 ···
Avatar
omochimetaru 25-Jan-18 06:05 AM
いろいろいいところあるけどアイコンのおかげで人物対応が記憶できるの大きいな
06:08
@noescape 懐かしい
Avatar
omochimetaru 25-Jan-18 07:52 AM
struct Cat : CustomStringConvertible { var name: String var description: String { return name } } var a: Cat = .init(name: "たま") var b: Cat? = .init(name: "くろ") // [1] print("\(a)") // [2] print("\(b?.description ?? "")") // [1] にたいして [2] の記述量が多く理不尽に感じる。 // 「noneなら空文字列」という事だけが言いたいだけなので、 // 例えば以下のように書きたい。 print("\(b ?? "")") // でもこれは ?? の両辺の型としておかしいので・・・ // 例えば \() を2引数関数のようにみなして print("\(b, "")") // などと書けるようにするとか?
07:53
最近の Optional(2018) から思っている事↑
Avatar
Kishikawa Katsumi 25-Jan-18 07:54 AM
\(b, defaultValue: "") の方がそれっぽいかなあ。 (edited)
07:54
でも良いアイデアと思いますね。
Avatar
rintaro 25-Jan-18 07:56 AM
print("\(b, "")") は現状でも書けちゃうという。 "\((b, ""))" と解釈される。
Avatar
omochimetaru 25-Jan-18 07:57 AM
!!! > 現状でも書けちゃう
Avatar
Kishikawa Katsumi 25-Jan-18 07:57 AM
Tupleになっちゃうのか。
Avatar
omochimetaru 25-Jan-18 07:57 AM
@Kishikawa Katsumi たしかに。Dictionaryのやつとかもそんな雰囲気ですし、そうですね
07:57
これが必要だと思う理由もう一個あって、
Avatar
Kishikawa Katsumi 25-Jan-18 07:57 AM
直したのにまだtypoしてるな。
Avatar
omochimetaru 25-Jan-18 07:57 AM
.description になるか、 .debugDescription になるか、 (3) になるか (4) になるか
07:58
(3, 4は省略 、とにかく4しゅるいある)
07:58
\(a) ってかいてるときは気にする必要が無いのに (edited)
07:58
デフォルトを与えようとしたときにはそれが露出するのもアンバランスだと思うからです
Avatar
koher 25-Jan-18 07:59 AM
これって大分進んだ議論な気がしていて、まずは文字列補間で CustomStringConvertible 以外使えないようにすることが必要そう。
👆 1
Avatar
tarunon 25-Jan-18 07:59 AM
途中まで作業してほったらかしで申し訳ない気持ち
Avatar
omochimetaru 25-Jan-18 08:00 AM
@koher @tarunon ですね、そっちの路線に行くならこれは寄り道です。現状を前提にマシにしていくなら、という方向で考えてます。
Avatar
tarunon 25-Jan-18 08:01 AM
Optional where Wrapped: CustomStringConvertibleなXにX ?? Stringのオペレーターを追加するとスッと書けそう
Avatar
omochimetaru 25-Jan-18 08:02 AM
そうだね、でもそれ若干おかしなことになってない?
08:02
文字列補間のことを一旦忘れて考えると、 ただのXはそのままではStringにならなくて .description がいるのに (edited)
08:02
Optional<X> は String にもっていくショートカットがあることになる
Avatar
tarunon 25-Jan-18 08:04 AM
確かに
08:05
それが文字列補完でしか使えないなら兎も角外に露出してるのは気持ちが悪いね
Avatar
omochimetaru 25-Jan-18 08:05 AM
そうそう。
08:05
僕のさっきのだとあくまで文字列補間の流れでの拡張だからそういう副作用は無い。
Avatar
koher 25-Jan-18 08:06 AM
foo?.description ?? "" は必要最小限の表記な気が。
08:06
あとは extension 生やして foo.description(default: "") くらい? (edited)
Avatar
omochimetaru 25-Jan-18 08:07 AM
optionalじゃないときは "\(foo)" だけで書けるのに、というモチベーションは変わらないですねえ
Avatar
koher 25-Jan-18 08:08 AM
↓に倣えば。
subscript(key: Dictionary.Key, default defaultValue: @autoclosure () -> Dictionary.Value) -> Dictionary.Value { get set }
https://developer.apple.com/documentation/swift/dictionary/2894528-subscript
Avatar
Kishikawa Katsumi 25-Jan-18 08:08 AM
メソッドやSubscriptはfooがnilの時は
08:08
呼ばれないから難しいんじゃないかな。
Avatar
koher 25-Jan-18 08:08 AM
optionalじゃないときは "(foo)" だけで書けるのに
Optional なのに空文字列に変換したいという特殊なニーズだから仕方ないんじゃないかなぁ?
Avatar
omochimetaru 25-Jan-18 08:09 AM
koher が書いてるのは Optional型自体のメソッドじゃないですか? .map などと同じ。
Avatar
koher 25-Jan-18 08:09 AM
↓ですね。
extension Optional where Wrapped : CustomStringConvertible { func description(default defaultValue: String) -> String { return self?.description ?? defaultValue } }
(edited)
Avatar
t.ae 25-Jan-18 08:09 AM
String(describing: )でいいんじゃないかと思ったんですがこの引数の型なんだろ……
Avatar
tarunon 25-Jan-18 08:10 AM
Any
Avatar
omochimetaru 25-Jan-18 08:10 AM
@t.ae Anyだし、それは "Optional(2018) " になるだけだよ (edited)
Avatar
hiragram 25-Jan-18 08:10 AM
あれそれはならないんじゃなかったっけ
Avatar
t.ae 25-Jan-18 08:10 AM
ドキュメントにSubjectって書いてあるんですがAnyのエイリアスなんですかね?
Avatar
hiragram 25-Jan-18 08:10 AM
なるんだっけ
Avatar
Kishikawa Katsumi 25-Jan-18 08:10 AM
Optionalの方を拡張するのもいいですけど、Fooにも両方拡張しないと使い勝手が悪くないです? (edited)
08:10
いや、いいのか。
08:11
OptionalじゃなければDefaultValueはいらないですね。
🙂 1
Avatar
omochimetaru 25-Jan-18 08:11 AM
print("\(String(describing: b))") // "Optional(くろ)\n" var c: Cat? = nil print("\(String(describing: c))") // "nil\n"
(edited)
Avatar
Kishikawa Katsumi 25-Jan-18 08:11 AM
まあOptionalのCustomStringConvertibleをなくすのが一番スッキリではありますね。
Avatar
tarunon 25-Jan-18 08:11 AM
OptionalはCustomDebugStringConvertibleですね
08:12
CustomStringConvertibleではないです
08:12
(ややこしや)
Avatar
omochimetaru 25-Jan-18 08:12 AM
www
Avatar
Kishikawa Katsumi 25-Jan-18 08:12 AM
じゃあOptionalでCustomStringConvertibleを新しく実装するようになればいいのか。
Avatar
koher 25-Jan-18 08:13 AM
OptionalはCustomDebugStringConvertibleですね CustomStringConvertibleではないです (ややこしや)
でもこれってよく考えるとそうなっていてほしくて、文字列に変換できちゃうと困るけど、デバッグ時には文字列にしたいんですよね。
Avatar
Kishikawa Katsumi 25-Jan-18 08:13 AM
"Optional(xxx)"じゃないやつ。
Avatar
tarunon 25-Jan-18 08:13 AM
なので、CondConf以後の世界では、extension Optional: CustomStringConvertible where Wrapped: CustomStringConvertible を自分で定義する、のはアリかもしれません。
08:13
僕はやらないけど
Avatar
koher 25-Jan-18 08:13 AM
OptionalCustomStringConvertible だと "Optional(2018年)" の温床になるのでダメだと思います。
Avatar
omochimetaru 25-Jan-18 08:13 AM
それだと none の場合の表記がアドホックに定義できないし。
Avatar
koher 25-Jan-18 08:14 AM
そうだね、今やりたいのは .none のときに "" にしたいって話だからまた違う。
Avatar
omochimetaru 25-Jan-18 08:14 AM
noneのときどうするかってのはコンパイラに怒られながらその場その場で決めていくものな感
Avatar
koher 25-Jan-18 08:15 AM
Conditional Conformance があっても、 extension Optional : CustomStringConvertible where Wrapped : CustomStringConvertible はまずそう。
Avatar
Kishikawa Katsumi 25-Jan-18 08:15 AM
私はInterpolationはこのまま置いといて、型が作用するTemplate表記みたいなものの方がいいと思っています。 (edited)
Avatar
omochimetaru 25-Jan-18 08:15 AM
extension String { init<X>(describing: Optional<X>, default: String) }
↑こういう選択肢も・・・・
08:15
ただ Optional<X> 自体をデバッグダンプする場合と曖昧になるんだよな。
Avatar
t.ae 25-Jan-18 08:16 AM
infix operator ??? func ???<T>(lhs: Optional<T>, rhs: String) -> String { return lhs.map(String.init(describing:)) ?? rhs } let a: Int? = 0 print("\(a ??? "empty")") let b: Int? = nil print("\(b ??? "empty")")
(edited)
08:16
では?
Avatar
omochimetaru 25-Jan-18 08:16 AM
型が作用するTemplate表記
@Kishikawa Katsumi これは、どんなものですか?
Avatar
Kishikawa Katsumi 25-Jan-18 08:16 AM
いわゆるprintfなんですけどコンパイル時に間違いがわかる。
Avatar
omochimetaru 25-Jan-18 08:16 AM
バックスラッシュパーレン \( ) とは別に用意する?
Avatar
Kishikawa Katsumi 25-Jan-18 08:17 AM
フォーマッタを渡してカスマイズできるとか。
Avatar
koher 25-Jan-18 08:17 AM
一番良く使われるのが "\(foo)" である以上、それで CustomStringConvertible でないものを弾けないと "Optional(2018年)" を防ぎきれないと思うんですよねぇ。
Avatar
Kishikawa Katsumi 25-Jan-18 08:17 AM
("% % %", a, b, c) <= なんかこんな感じの。
Avatar
omochimetaru 25-Jan-18 08:17 AM
@t.ae それは @tarunon が最初に書いてくれた例に近くて、 文字列補間と関係ないところでもその演算子が使えちゃうのがdirtyに思うんだよね。
Avatar
t.ae 25-Jan-18 08:18 AM
露出するのはそうですね。
Avatar
Kishikawa Katsumi 25-Jan-18 08:19 AM
String Interpolationは大して便利でもないけど、中途半端に書きやすいからそっち使おうとするので、
08:19
同等程度に書きやすくて便利なものがある方がいい。
Avatar
omochimetaru 25-Jan-18 08:20 AM
あ〜
Avatar
Kishikawa Katsumi 25-Jan-18 08:20 AM
foo?.description ?? "" このように書くのは全く正しいけど、長いからこう書きたくないってことなので。 (edited)
Avatar
omochimetaru 25-Jan-18 08:20 AM
単純な文字列化したいときにも "\(a)" って書いちゃうケースを考えているんですね。 (edited)
08:21
なんかこういうケースを考えてました↓
return "User(name=\(name), petCat=\(cat))"
Avatar
koher 25-Jan-18 08:21 AM
今の話で思い出したけど、↓で警告も出ないのイケてないから CustomStringConvertible でないものを文字列補間に突っ込んだら警告がいいと思うんですがどうでしょう?
struct Foo {} let foo = Foo() print("\(foo)") // Foo()
(edited)
Avatar
omochimetaru 25-Jan-18 08:22 AM
あ、でもこれもまあ String(format: "") 的に書くことができるか。
08:22
個人的には書式置換よりも文字列補間の方が良いと思っていて、そっちを洗練させたいんですよね。
08:22
理由は、流れで読んだときにどこに何が埋め込まれるかわかりやすいからです。 書式だと、プレースホルダと値の対応が左と右に分離していてわかりにくい。
Avatar
Kishikawa Katsumi 25-Jan-18 08:23 AM
プレースホルダと値の対応が左と右に分離していてわかりにくい。
08:23
それは同意です。
Avatar
tarunon 25-Jan-18 08:23 AM
@koher それはそのとおりだと思っていて、半年ほど前に実現しようとコンパイラをいじって,そのままほったらかしになってます 😿
Avatar
koher 25-Jan-18 08:23 AM
おお、そうなんですね
Avatar
tarunon 25-Jan-18 08:23 AM
だれかやってくれ~
08:23
先にプロポーザル投げちゃってもいいのかな
Avatar
omochimetaru 25-Jan-18 08:23 AM
今の話で思い出したけど、↓で警告も出ないのイケてないから CustomStringConvertible でないものを文字列補間に突っ込んだら警告がいいと思うんですがどうでしょう?
それはそれで同意で、 @tarunon を応援していた
Avatar
koher 25-Jan-18 08:24 AM
@tarunon Pitch だけなら良さそう
08:24
Proposal 作るときは実装もいるけど
08:24
機能の @d_date さんみたいに Pitch だけなら OK かと。
Avatar
tarunon 25-Jan-18 08:24 AM
途中までやったんだけど、コンパイルエラーになるべきところがオレオレワーニングで上書きされて涙を流した
😭 1
Avatar
omochimetaru 25-Jan-18 08:24 AM
別のトピックとして、 String(format: "") が ObjC 由来で、 Swifty な標準がほしいという気持ちありますね
Avatar
Kishikawa Katsumi 25-Jan-18 08:24 AM
自分が書きたいっていうのでなければ、アイデアとして放流したら誰かが助けてくれるのでは。
Avatar
tarunon 25-Jan-18 08:25 AM
ピッチの機運高まってきた
08:25
やるか~
Avatar
omochimetaru 25-Jan-18 08:25 AM
@d_date がハードル下げてくれた感ある。
🙏 1
Avatar
d_date 25-Jan-18 08:25 AM
ここで揉んでforumに投げられるフローありがたいです🙏
🙂 2
Avatar
koher 25-Jan-18 08:27 AM
いきなりぶっこむと考え違いとか抜け漏れがありそうですし、英語で不毛な議論するの辛いですしね。
Avatar
koher 05-Feb-18 04:45 AM
今日はいつものメンバーの興味深い会話が Twitter で行われている模様。 https://twitter.com/omochimetaru/status/960373117376872448
@hiragram その2 「2行以上あるときに目に止めて内容をチェックすべき」よりも良い状態になる。 unwrapの利用を促進することで「guardがあるところにはただ死ぬ以外の何かが必ずある」 ことになる。
🙂 1
Avatar
hiragram 05-Feb-18 04:45 AM
Avatar
d_date 05-Feb-18 04:45 AM
きっとあとでtogetterにまとめられて見やすくなる👀
Avatar
tarunon 05-Feb-18 04:45 AM
リプライたどるだけで良いのでは
04:46
結論のでたツイートをここに貼れば全員幸せになれるよ
Avatar
hiragram 05-Feb-18 04:46 AM
第三者がメンションナシで絡んできてからがtogetter
Avatar
d_date 05-Feb-18 04:46 AM
あ、スレッドだった
Avatar
tarunon 05-Feb-18 04:49 AM
ところでTwitter公式まとめ機能ができてたのでそれでも良い気がする(Toggetterの人ごめんね)
04:49
使いやすいかは知らない
Avatar
rintaro 05-Feb-18 06:43 AM
class Foo { init!() { return nil } }
init! 定義できるのに今更気づいたのですが、完全に使いどころがわからない。
(edited)
Avatar
tarunon 05-Feb-18 06:44 AM
激ヤバトラップだ
Avatar
rintaro 05-Feb-18 06:45 AM
ちょっと考えられるのが、 convenience init から self.init() で呼べるっていうのだけど、それにしても (edited)
06:46
init?()self.init()! で呼べるし。
06:47
廃止したほうがいいんじゃないか。
06:52
func foo() -> Int! も一緒ですね。廃止して欲しい。
Avatar
tarunon 05-Feb-18 06:52 AM
どっちもObjCブリッジングで入り用になりそうな気がしますねぇ
Avatar
norio_nomura 05-Feb-18 06:56 AM
CHANGELOG.mdに記述がありますね。
### 2014-10-09 (Xcode 6.1) * Objective-C `init` and factory methods are now imported as failable initializers when they can return `nil`. In the absence of information about a potentially-`nil` result, an Objective-C `init` or factory method will be imported as `init!`.
今でもあるのかな?
Avatar
rintaro 05-Feb-18 07:00 AM
なるほどー。アトリビュートついてないObjCのブリッジングはそうせざるを得ないということなのですね。
Avatar
norio_nomura 07-Feb-18 08:51 AM
func f(_ value: Int?) {} @available(*, deprecated) func f(_ value: String?) {} f(nil) // error: ambiguous use of 'f'
deprecatedが付いてたら優先順位を変えてambiguous回避出来て欲しい。
Avatar
lovee 07-Feb-18 09:43 AM
unavailable はどうでしょう?
Avatar
norio_nomura 07-Feb-18 09:56 AM
nil以外だとambiguousにならないので、残せるなら残したいのです。
Avatar
tarunon 07-Feb-18 11:31 AM
前RxSwiftが踏んでましたね
Avatar
omochimetaru 07-Feb-18 11:32 AM
ライブラリが型設計を改善するときにオプショナルが絡んでるだけで踏みそう
Avatar
tarunon 07-Feb-18 01:12 PM
RxSwiftが踏んだのは、defaultValueをnilにしていて、それ以外のラベルが全く同じ場合だった
13:13
deprecated,unavailableで優先してくれれば発生しない問題ではある
Avatar
norio_nomura 07-Feb-18 01:27 PM
unavailable指定はambiguous回避出来ますが、書き換え強制になっちゃうんですよね。
Avatar
koher 09-Feb-18 02:10 PM
async な関数って inout で渡された引数にアクセスできるのは最初の await までだけになるのかな?
14:13
↓のページ内を inout で検索してもヒットしない・・・。 https://gist.github.com/lattner/429b9070918248274f25b714dcfc7619
Concrete proposal for async semantics in Swift
Avatar
omochimetaru 09-Feb-18 04:30 PM
そもそも使えないんじゃないですかねえ
16:32
そもそもinout引数はエスケープもできないし。
func aaa(_ x: inout Int) -> () -> Void { func bbb() { x = 3 } return bbb } var t: Int = 3 aaa(&t)
16:33
Swift:: Error: nested function cannot capture inout parameter and escape return bbb ^ Swift:: Error: expression resolves to an unused function aaa(&t) ^~~~~~~
Avatar
koher 09-Feb-18 05:02 PM
最初の await までは使えてほしいなぁ。
Avatar
koher 09-Feb-18 06:02 PM
@omochimetaru ↓これは @escaping でもできるっぽい。当然 @escaping しようが同期的な範囲でしか使えないけど。
func update<T>(_ value: inout T, _ operation: @escaping (inout T) -> ()) { operation(&value) }
Avatar
norio_nomura 12-Feb-18 12:56 PM
SourceKitにlibSyntaxのシリアライズデータを返す機能が追加されてたみたいだけど、どう活かすのだろう? https://github.com/apple/swift/pull/14000
The enhanced SourceKitd requests are EditorOpen and EdtiorReplaceText. In these two requests, the clients can specify a flag "key. enablesyntaxtree = 1" to get a serialize libSyntax tree with the r...
Avatar
omochimetaru 12-Feb-18 01:40 PM
libSyntaxの呼び出しがSourceKitAPI経由になるPRもこの間入ってたのでそのための口じゃないですかね
Avatar
omochimetaru 12-Feb-18 02:08 PM
それはそれとして、libSourceKitの内部的な下請けの処理も、libSyntax用の実装に差し替わっていくのかもしれないですけど。
Avatar
norio_nomura 12-Feb-18 02:18 PM
良く知らないのですが、libSyntaxってそんな用途を考えられた感じなのですか?
14:19
初見ではそんな感じには見えなかったのですが。
Avatar
omochimetaru 12-Feb-18 02:20 PM
基本的にはパーサー部分を綺麗に作り直すプロジェクトだと思ってます
Avatar
norio_nomura 12-Feb-18 02:23 PM
そうなんだ。
14:26
SwiftSourceKitClientとか出来るのか。
Avatar
koher 13-Feb-18 01:34 PM
@d_date ご存知かもしれませんが、 Proposal の Status が "Awaiting implementation" になってます。 https://github.com/apple/swift への実装の PR との紐付けが必要かと。↓のように Proposal に Implementation の項目が必要です。
* Implementation: [apple/swift#13361](https://github.com/apple/swift/pull/13361)
https://github.com/apple/swift-evolution/blob/master/proposals/0195-dynamic-member-lookup.md
After reflecting on the evolution process during both the Swift 3 and Swift 4 releases, the Core Team felt that we could strike a balance with not diluting attention from ABI stability while still enabling a broader range of proposals compared to Swift 4 by **requiring that all proposals have an implementation** before they are officially reviewed by the Core Team.
https://forums.swift.org/t/swift-5-start-your-engines/6456
swift - The Swift Programming Language
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Hi everyone, The proposal phase for Swift 4 is now officially over, and the release is now in endgame engineering convergence for an expected release later this year. Swift 4 has turned out to be one of the highest quality, well-rounded releases of Swift, and I am grateful to everyone in the community who made this release come together! Now it is time to turn our attention to Swift 5. I have just posted updates to the README.md file on the swift-evolution repository, which outlines the core...
Avatar
d_date 14-Feb-18 01:09 AM
@koher ありがとうございます!実装中です🙏 (edited)
🙂 1
01:11
返信先まちがったw
🙃 1
Avatar
koher 15-Feb-18 08:31 AM
#swift-zatsu から移動。
08:31
Kotlin なら break: () -> Never 作れそう。
08:32
どうしても今の Swift で async/await 相当のことできないと辛くなって、 Promise 改造して↓を作ったけど、 https://github.com/koher/AsyncK
AsyncK - An alternative of async/await in Swift
08:34
非同期ループできないと辛いから↓ asyncFor を作って、 break() -> Never にできないか考えたけどダメだった。
func asyncFor<S: Sequence>(_ sequence: S, _ operation: @escaping (S.Element, _ break: @escaping () -> ()) -> Async<Void>) -> Async<Void>
https://github.com/koher/AsyncK/blob/master/Sources/AsyncK/Async.swift#L80
AsyncK - An alternative of async/await in Swift
Avatar
koher 22-Feb-18 05:21 AM
Swift コンパイラかしこい。↓はコンパイルエラーになるけど、 AProtocol: class にしたらエラーなくなる。
protocol AProtocol { var value: Int { get set } } struct B<T: AProtocol> { private let t: T init(_ t: T) { self.t = t } func get() -> T { return t } } class A: AProtocol { var value: Int init(value: Int) { self.value = value } } func foo<T: AProtocol>(a: T) { let b = B<T>(a) b.get().value += 1 // ここでコンパイルエラー print(b.get().value) } foo(a: A(value: 2))
Avatar
omochimetaru 22-Feb-18 05:28 AM
右辺値(get()の返り値)が値型の時はプロパティアクセスが左辺値として使えないけど 参照型の時はプロパティアクセスが左辺値として使える というルールが、プロトコルのclass制約に対して考慮されているんですね
Avatar
koher 22-Feb-18 05:29 AM
はい、そうです。
Avatar
omochimetaru 22-Feb-18 05:30 AM
get() の代わりに subscript にすると、subscript は右辺値じゃなくて左辺値を返すから、 b のmutabilityが伝搬して、 このままなら var b が必要、 : class が付くなら let b で OK 、になるかな
Avatar
koher 22-Feb-18 05:32 AM
subscript だと引数がいるから computed property がいいかも
Avatar
omochimetaru 22-Feb-18 05:33 AM
たしかに
Avatar
rintaro 22-Feb-18 05:36 AM
一応注意喚起しておくと class 制約は AnyObject と同意になり、 class は deprecated です。 https://github.com/apple/swift-evolution/blob/master/proposals/0156-subclass-existentials.md#class-and-anyobject
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
omochimetaru 22-Feb-18 05:36 AM
deprecated・・・!?
⁉ 1
Avatar
rintaro 22-Feb-18 05:37 AM
: AnyObject でまったく同じ意味になるので、機能が同じものを残しておく必要は無いということですね。
Avatar
omochimetaru 22-Feb-18 05:37 AM
To reduce source-breakage to a minimum, class could be redefined as typealias class = AnyObject and give a deprecation warning on class for the first version of Swift this proposal is implemented in.
05:38
あれ〜 気づかなかったな まだ警告は出ない?
Avatar
rintaro 22-Feb-18 05:38 AM
まだ出ないみたいですね
Avatar
koher 22-Feb-18 05:38 AM
同じく気付いてませんでした。前に見たけど忘れてたのかなぁ・・・。最近はずっと : class してた気がする。
Avatar
tarunon 22-Feb-18 05:43 AM
AnyObject、振る舞いが特殊すぎてなかなかこう
Avatar
omochimetaru 22-Feb-18 05:43 AM
特別な存在
Avatar
tarunon 22-Feb-18 05:43 AM
いやまじで
05:43
BuiltIn.AnyObject、凶悪
Avatar
omochimetaru 22-Feb-18 05:44 AM
そこらへんの特別扱いがあるから、値型と参照型が言語の中で同じようなノリで使える
05:45
厳密にしてしまうと、C++やRustみたいに参照型の取扱が型システム側で陽に露出して、アプリを書くのには面倒になる
Avatar
koher 22-Feb-18 05:45 AM
AnyObject と言えば、 Swift の関数(クロージャ)は参照型だけど ===AnyObject に対してしか使えなくて関数の同一性の比較ができないのどうにかならないのかな?
05:47
厳密にしてしまうと、C++やRustみたいに参照型の取扱が型システム側で陽に露出して、アプリを書くのには面倒になる
うーん、参照型と値型を混ぜて扱うの、挙動のイメージが人間の(僕の?)認知能力を超えててヤバイ気がするんだけどなぁ。
05:48
protocolinterface 作って、 protocol は値型、 interface は参照型と分けてしまってもいいんじゃないかという気がする。
Avatar
tarunon 22-Feb-18 05:49 AM
protocol MyProtocol: AnyObject { } class Foo: MyProtocol { } func foo<X>(_ v: X) where X: MyProtocol {} func bar<X>(_ v: X) where X: AnyObject {} let a: MyProtocol = Foo() let b: AnyObject = Foo() // foo(a) // 🙅 // bar(a) // 🙅 bar(b) // 🙆
05:49
これなんやが
05:50
例のProtocol変数はExisitential~の件で色々調べてて行き当たって
05:51
AnyObject とは一体…ってなったやつ
Avatar
koher 22-Feb-18 05:51 AM
おおお・・・
05:51
いや、でも Any も同じ?
Avatar
omochimetaru 22-Feb-18 05:52 AM
bの型のAnyObjectは本当の型としてのAnyObjectで、 MyProtocol : AnyObjectやwhereのAnyObjectは型制約のAnyObjectで、 aの型のMyProtocolはExistentialだから自身を満たさないw
Avatar
tarunon 22-Feb-18 05:53 AM
これは本当に難しい
Avatar
omochimetaru 22-Feb-18 05:53 AM
難しいね・・・
Avatar
tarunon 22-Feb-18 05:53 AM
public typealias AnyObjectってなってるのがね
Avatar
omochimetaru 22-Feb-18 05:53 AM
b: AnyAnyObject って感じだよね
Avatar
tarunon 22-Feb-18 05:53 AM
事実上の振る舞いとしてはpublic class SwiftObjectのタイプエイリアスなんだろうなというのはわかる
05:54
つまり、protocolの制約に使えるという特殊ルールを付加されたクラス型、そして汎ゆるクラス型のスーパータイプでもある。
😇 1
05:55
Anyも確かに似たような振る舞いしますね。
Avatar
koher 22-Feb-18 05:55 AM
うーん、↑を考えると protocol Foo: AnyObject より protocol Foo: class の方がいい気がする・・・。
🙌 3
Avatar
omochimetaru 22-Feb-18 05:55 AM
もう遅いw
😭 1
Avatar
koher 22-Feb-18 05:56 AM
さっきの Proposal にその辺りの議論まで書かれてるのかな?
Avatar
tarunon 22-Feb-18 05:56 AM
因みにこれですね、@objc が入ると更に大変なことになる
Avatar
omochimetaru 22-Feb-18 05:56 AM
// foo(a) // 🙅 // bar(a) // 🙅
もうこのまま突き進んでこれが通る方に倒したい
Avatar
tarunon 22-Feb-18 05:57 AM
それExistentialじゃなくなるw
Avatar
omochimetaru 22-Feb-18 05:57 AM
自動Erasure方式
Avatar
tarunon 22-Feb-18 05:57 AM
暗黙的にopenするのやばそう
05:57
まあでも関数呼び出しは既に暗黙openingやし
Avatar
koher 22-Feb-18 05:58 AM
普通の protocol の existential ですでにそうなのが・・・
Avatar
tarunon 22-Feb-18 05:58 AM
import Foundation @objc protocol MyProtocol: AnyObject { } class Foo: NSObject, MyProtocol { } func foo<X>(_ v: X) where X: MyProtocol {} func bar<X>(_ v: X) where X: AnyObject {} let a: MyProtocol = Foo() let b: AnyObject = Foo() foo(a) // 🙆 bar(a) // 🙆 bar(b) // 🙆
😇 1
05:58
@objc protocolは最早何でもあり (edited)
05:59
そっか、この視点から見るとAnyObjectは振る舞いとしては@objc protocolに限りなく近い (edited)
Avatar
omochimetaru 22-Feb-18 06:00 AM
@objc が付いた protocol は型として使うとExistentialじゃなくなる?w
Avatar
tarunon 22-Feb-18 06:00 AM
Existentialじゃないっぽいですね
Avatar
koher 22-Feb-18 06:00 AM
タイトルしか読んでないけど↓で変わったりしないのかな? https://forums.swift.org/t/objective-c-interoperability-eliminate-nsobjectprotocol/9947
Hi all, TL;DR I propose to completely eliminate the NSObject protocol (called NSObjectProtocol) from Swift, leaving only a deprecated typealias (to AnyObject) as a backward-compatibility shim. Motivation The Objective-C NSObject protocol, imported into Swift as NSObjectProtocol, is more harmful than helpful in Swift: The API it provides is not particularly useful in Swift, either because the functionality is better expressed via Swift language features (is and as? rather an isKind(of:) or c...
Avatar
omochimetaru 22-Feb-18 06:01 AM
そのスレ気になってるけどヤバそうで読んで無いわ・・・
Avatar
tarunon 22-Feb-18 06:04 AM
%10 = open_existential_ref %9 : $Animal to $@opened("00DAD0B2-1796-11E8-B1A7-8C85902C8E53") Animal // users: %12, %12, %11 %11 = witness_method [volatile] $@opened("00DAD0B2-1796-11E8-B1A7-8C85902C8E53") Animal, #Animal.bark!1.foreign : <Self where Self : Animal> (Self) -> () -> String, %10 : $@opened("00DAD0B2-1796-11E8-B1A7-8C85902C8E53") Animal : $@convention(objc_method) <τ_0_0 where τ_0_0 : Animal> (τ_0_0) -> @autoreleased NSString // type-defs: %10; user: %12 %12 = apply %11<@opened("00DAD0B2-1796-11E8-B1A7-8C85902C8E53") Animal>(%10) : $@convention(objc_method) <τ_0_0 where τ_0_0 : Animal> (τ_0_0) -> @autoreleased NSString // type-defs: %10; user: %14
06:04
open_existential_ref って書いてあったわ、 @objc protocol
Avatar
omochimetaru 22-Feb-18 06:05 AM
なるほど
Avatar
tarunon 23-Feb-18 03:48 AM
@takasek さっきの #swift-zatsu の話
03:48
完全にワークアラウンドなんだけど
03:48
class ReadWrite { } class ReadOnly: ReadWrite { } protocol IO { associatedtype Manifest: ReadWrite = ReadOnly } func foo<P>(_ arg: P) where P: IO, P.Manifest: ReadWrite { // ReadWrite }
03:49
こんな風にassociatedtypeにFantomTypeを埋め込んでデフォルト型を定義しておくと
Avatar
omochimetaru 23-Feb-18 03:49 AM
メンション先あってる? (edited)
Avatar
tarunon 23-Feb-18 03:49 AM
意図した型以外は弾けるようになってる
03:49
あれ
03:49
ごめん、 @lovee だったw
😇 2
Avatar
omochimetaru 23-Feb-18 03:50 AM
typealiasで明示的にManifestをReadOnly ReadWriteに設定していない型だけ通るようになるのか (edited)
Avatar
tarunon 23-Feb-18 03:51 AM
えっと
03:51
明示的にManifestをReadWriteにしないと
03:51
自動でReadOnlyになるんだな
03:51
assoctypeはGenericsと違ってデフォルト型が定義できる
Avatar
omochimetaru 23-Feb-18 03:52 AM
デフォルトのゆるい型は駄目にして
Avatar
tarunon 23-Feb-18 03:52 AM
ん?ちょっと辺だった待ってw
Avatar
omochimetaru 23-Feb-18 03:52 AM
指定した狭い型のための定義を用意する?
Avatar
tarunon 23-Feb-18 03:52 AM
class ReadOnly { } class ReadWrite: ReadOnly { } protocol IO { associatedtype Manifest: ReadOnly = ReadOnly } func foo<P>(_ arg: P) where P: IO, P.Manifest: ReadWrite { // ReadWrite } class UserDefaults: IO { } foo(UserDefaults()) // 🙅
(edited)
03:52
これが正しい
Avatar
omochimetaru 23-Feb-18 03:52 AM
@lovee がやりたいのは型パラメータ T が Optional では無いって条件みたいだけど適用できる?
03:53
@tarunon 方式だとある具象型についてManifestを設定しないといけないから、駄目な気がする。
Avatar
tarunon 23-Feb-18 03:53 AM
それはそう
03:53
うーん
03:53
TがOptionalでない、はちょっと無理筋な気がしていて
03:54
SwiftのOptionalはnullabelじゃなくて型なので
03:54
そもやりたいことを考えたほうが良さそう。
Avatar
omochimetaru 27-Feb-18 01:57 AM
classのmutating funcが無いと書けないやつがあるのはそうだかど
01:57
書けなくても良いのでは @koher
Avatar
lovee 27-Feb-18 01:58 AM
まあユースケースは確かにイマイチ思いつかないですね、どういう状況でしょう? 🤔
Avatar
koher 27-Feb-18 01:59 AM
イミュータブルクラスでは自身の更新を新規インスタンスを生成して再代入で行いますが
01:59
var foo = ImmutableFoo() foo = foo.update(...)
02:01
これを
var foo = ImmutableFoo() foo.update(...)
でできて代入が不要になります。 immutable なのに mutating なのは名前がややこしいですが、 immutability は失われてないです。
02:01
イミュータブルクラスで mutating func を使えても、 self 自体の置き換えはできてもインスタンスの状態は変更できないのでインスタンスの immutability は保たれます。 (edited)
02:02
まあ、値型使えばいいんですが。
Avatar
lovee 27-Feb-18 02:02 AM
理屈は確かにそうですが、ただ class 自身が自分のオブジェクトを書き換えるのはどういうシチュエーションなのかが気になるんですね 🤔
Avatar
koher 27-Feb-18 02:03 AM
↑のシチュエーションはどうですか?
02:03
Swift でイミュータブルクラスを作るシチュエーション自体があまりないかもしれませんが。
Avatar
omochimetaru 27-Feb-18 02:04 AM
うーん・・・
Avatar
koher 27-Feb-18 02:04 AM
そもそも値型だろうと self 置き換えがあまりないのかな?
Avatar
omochimetaru 27-Feb-18 02:04 AM
もしclassにmutating funcとnonmutating funcがあったとしたら
02:04
ふつうにユーザーが想像するのは
02:04
self書き換えを示すアトリビュートではなくて
Avatar
tarunon 27-Feb-18 02:05 AM
型システムの都合上classにするしかないが値型相当の取り扱いをしたい、というのはあり得るかなー
Avatar
omochimetaru 27-Feb-18 02:05 AM
stored propetyの変更を許すかどうか
02:05
っていうアトリビュートであることが期待されますよね。
Avatar
koher 27-Feb-18 02:05 AM
@tarunon ですねー。 Promise とかそれで class にしてます。
Avatar
hironytic 27-Feb-18 02:05 AM
そもそもclassだと複数の変数から参照されるから、 self 書き換えというのがいまひとつどれを書き換えているのか。
Avatar
koher 27-Feb-18 02:05 AM
@omochimetaru うん。 self 置き換え可能と、プロパティを書き換え可能は独立した機能な気がしてる。
Avatar
tarunon 27-Feb-18 02:06 AM
そういう場面でmutating funcは欲しいかもしれない。Rxだとsinkぶん投げて新しいObservable毎回作ってますが、そういう系でほしい場面はあるかも?
Avatar
koher 27-Feb-18 02:06 AM
プロパティの書き換え可能は class にとっては暗黙的に保証されてるけど、それとは別に var に格納されているときに self を書き換えられるという機能があり得るような。
Avatar
lovee 27-Feb-18 02:06 AM
@hironytic 確かに 🤔 全部ってなるとなんかバグりそうな気がしないでもない
Avatar
omochimetaru 27-Feb-18 02:07 AM
全部は原理的に実装不可能でしょうね 呼び出し元のvarだけかと。
Avatar
hironytic 27-Feb-18 02:07 AM
まあ、全部はないですよね。 varlet の両方から参照されていることもあるから。
Avatar
koher 27-Feb-18 02:07 AM
mutating func というか inout self をしたい。
Avatar
rintaro 27-Feb-18 02:08 AM
もしどうしてもやりたいんだったら、 protocol extension で 出来るので可能といえば可能なのですが、僕はそのAPIはちょっと気持ち悪いです。
Avatar
tarunon 27-Feb-18 02:08 AM
factory init術だ
Avatar
omochimetaru 27-Feb-18 02:09 AM
既存仕様の傷口を広げられるようにしたいかどうか、みたいな感じ
02:10
protocol existentialで扱ってる時は実際そうなるからな・・・
02:11
# 導入 Swift には struct と class があります。 struct のメソッドには func ( nonmutating func の省略表記 ) と mutating func がありますが、 cla...
Avatar
koher 27-Feb-18 02:15 AM
おお、ほんとだできた。
protocol CharacterProtocol { init(name: String, hp: Int) var name: String { get } var hp: Int { get } mutating func update(hp: Int) } extension CharacterProtocol { mutating func update(hp: Int) { self = Self.init(name: name, hp: hp) } } class Character: CharacterProtocol { let name: String let hp: Int required init(name: String, hp: Int) { self.name = name self.hp = hp } } var character = Character(name: "ゆうしゃ", hp: 153) character.update(hp: character.hp - 10)
Avatar
lovee 27-Feb-18 02:15 AM
//: Playground - noun: a place where people can play import UIKit protocol SelfRewritable { var id: Int { get set } init(id: Int) mutating func increaseID() } extension SelfRewritable { mutating func increaseID() { self = Self(id: self.id + 1) } } class User: SelfRewritable { var id: Int required init(id: Int) { self.id = id } } var user = User(id: 0) user.increaseID() user.id
02:15
同じことやろうとしてたw
🙃 1
Avatar
hironytic 27-Feb-18 02:17 AM
var foo = Foo() var bar = foo bar.update(...)
ってやったら、 foobar は別のものを指すようになるってことですよね。
Avatar
tarunon 27-Feb-18 02:17 AM
多分だけど、classのmutating funcの正しい動きは、「そのアドレスを参照する全ての変数でアドレスを変更」ではなく「mutating funcを呼び出した変数のアドレスを変更」がやりたいこと
02:17
なので出来るようにしても壊れないんじゃないかなーと思うのだけれども。
Avatar
omochimetaru 27-Feb-18 02:18 AM
壊れないことは壊れないと思います
Avatar
hironytic 27-Feb-18 02:18 AM
update がmutating funcかどうかがパッと見た目にわからないから、ぼくはそれは嫌かなー。
Avatar
lovee 27-Feb-18 02:19 AM
なんかここの動作を保証したいなら、protocol: valueType が欲しいかな、mutating func 入れたい場合は
Avatar
koher 27-Feb-18 02:20 AM
微妙さはあると思いますが、同じことは値型にも言える気がするんですよね。 < update がmutating funcかどうかがパッと見た目にわからないから
Avatar
hironytic 27-Feb-18 02:20 AM
いや、値型はもともと共有されないので。
Avatar
omochimetaru 27-Feb-18 02:20 AM
@lovee そこなんですけど、protocolとして扱うっていうのは、そもそも値的だと捉えるべきなんかなと最近思います
Avatar
koher 27-Feb-18 02:21 AM
イミュータブルクラスの場合、値型と同じだと思うんですよね。
Avatar
tarunon 27-Feb-18 02:21 AM
割りとある
Avatar
hironytic 27-Feb-18 02:21 AM
Mutableなクラスの場合は、共有している状態でupdateすることがあるじゃないですか。でも、言語的に、MutableなクラスかImmutableなクラスかもわからないので。
Avatar
tarunon 27-Feb-18 02:21 AM
class + convertible protocolで作ってstruct/enumとかはconvertible protocolに流すのが最近のワイのトレンド
Avatar
koher 27-Feb-18 02:22 AM
値型的だけど実装の都合上クラスにせざるを得ないときに、値型と同じように振る舞わせたい( API をそろえたい)ケースがあり得る気がしています。
Avatar
hironytic 27-Feb-18 02:22 AM
Immutableなクラスに限定すれば値型と同じようなものというのには同意します。
Avatar
koher 27-Feb-18 02:23 AM
たとえば↓のようなメソッドが標準ライブラリに追加されたとして
extension Array { mutating func update(_ operation: (inout Element) -> ()) }
02:24
Optional にも同じものを追加することはできますが、
02:24
class で実装された Promise は同じような API を持っているのに update を追加できません。
02:25
僕も積極的にほしいというほどじゃないんですが
Avatar
omochimetaru 27-Feb-18 02:25 AM
classをラップしたCoWなstructを作るのは?
Avatar
koher 27-Feb-18 02:25 AM
現象を切り分けて整理するとそういうケースがありうるなと。
Avatar
omochimetaru 27-Feb-18 02:26 AM
今話してるシチュエーションが、Arrayそれ自体の実装において起きてることな気がする。
Avatar
koher 27-Feb-18 02:26 AM
で、今の mutating funcinout self が混ざってしまっているのは、異なるものを一緒くたにしてしまっている気がします。
02:27
@omochimetaru struct ラップはあり得るけど、 Array の場合はミュータブルだからラップが必要だけど、 Promise の場合イミュータブル的に振る舞うから、本来不要なラッパーができるのが微妙かなぁ。
Avatar
omochimetaru 27-Feb-18 02:27 AM
一緒くたにしてるのはそう思います、値型に限って一緒くたにしてもいけるやろ!っていう機能ですよね
02:29
不要なラッパーは増えるけど、言語機能の複雑さを増やさずにすみます @koher
Avatar
koher 27-Feb-18 02:33 AM
値型に限って一緒くたにしてもいけるやろ!っていう機能ですよね
うん。今さらどうにもできないけど、本来であれば分けておくことでシンプルにできた気がする。
Avatar
omochimetaru 27-Feb-18 02:36 AM
classの実装でもstored propertyの変更を防止した実装ができるようになるけど
02:36
その場合、プロパティでクラスのインスタンスを持つ場合に
02:37
変数の型に対して参照不変性とオブジェクト不変性を記述しないといけないので
02:38
mutating var cat: Cat var cat: Cat mutating let cat: Cat let cat: Cat
02:38
を使い分けるプログラミングみたいになりますね
02:39
c++がコレ。
Avatar
tarunon 27-Feb-18 02:41 AM
んほー
02:41
よく見るやつだ
Avatar
koher 27-Feb-18 02:42 AM
@omochimetaru self 置き換えはまた別じゃない?
Avatar
omochimetaru 27-Feb-18 02:45 AM
@koher self置き換えができない変数の型がないと、structでnonmutatingのなかでプロパティのself書き換えが起きたら困る
Avatar
koher 27-Feb-18 02:47 AM
mutating funcself 置き換えができないようにして、それとは別に self 置き換えがあって区別できるのがいいかなと。そしたら、前者は var な値型のみ、後者は var ならクラスでも使えるようになる。
Avatar
omochimetaru 27-Feb-18 02:49 AM
ああなるほど
02:50
じゃあletなクラスがmutating funcを呼ぶことは許すわけですね
02:50
現状に対する追加的な仕様としてはまとまりますね
Avatar
koher 27-Feb-18 03:18 AM
↑の mutating func が構文のことではなく(今の Swift の class のインスタンスメソッドと同じように) Stored Property を変更可能なメソッドのことならそうです。
Avatar
omochimetaru 27-Feb-18 03:23 AM
はい struct は今と同じ class には 新たに mutating func と update func を導入 class は今まで func で stored property が変更可能だったがこれを禁止 stored property の変更は mutating func の中でのみ可能に変更 update func では実装文中で self への代入が可能 mutating funcとupdate func は同時指定可能 (mutating update func がある) という仕様にして class Cat { ... } var cat: Cat に対しては mutating func は呼び出し可能、 update func は呼び出し可能 let cat: Cat に対しては mutating func は呼び出し可能、 update func は呼び出し不可能 これまでの struct の mutating func については、暗黙に mutating update func とする とすれば var / let 変性は update func の呼び出しを制限するものとして互換性が通る。
03:28
この拡張のメリット ・class実装時においてもstored propertyの変更を静的にチェックされたコードが書ける ・self変更の概念がstruct/classで共通化されてわかりやすくなる
Avatar
koher 27-Feb-18 03:29 AM
僕のイメージは↓です。↑の update func という構文を踏襲するなら。 - mutating func は値型にのみ使用可能で Stored Property を更新可能、 self 置き換えは不可能、変数のような可変な lvalue に対してのみ呼び出し可能 - update func は値型にも参照型にも使用可能で self 置き換えが可能、変数のような可変な lvalue に対してのみ呼び出し可能 (edited)
03:30
protocolmutating funcclass でどうなるかは考え中。
Avatar
omochimetaru 27-Feb-18 03:32 AM
値型の場合、全てのstored propertyを書き換える事でself書き換えと同じ効果が発生させられるので、update func と mutating func を分ける意味が無いのでは?
Avatar
lovee 27-Feb-18 03:36 AM
メモリ的な意味では値型はプロパティーの書き換えとselfの書き換えは等価ですが、ただ例えばどうしてもイニシャライザーを通して生成したいもの( Range とか)ですと update func と mutating func の区別は生じる気がしないでもない 🤔
03:36
RangelowerBoundupperBound は let 宣言なので
Avatar
omochimetaru 27-Feb-18 03:36 AM
なるほど!
Avatar
koher 27-Feb-18 03:44 AM
逆に言うと mutating func を呼び出しても let プロパティは変更されないことが保証できるようになるね。
Avatar
omochimetaru 27-Feb-18 03:45 AM
struct Stone {} let stone: Stone に対する stone の mutating func は呼び出せないのでは? それを呼び出せるようにするってことですか?
Avatar
koher 27-Feb-18 03:49 AM
@omochimetaru
struct Character { let name: String var hp: Int mutating func foo() { self = Character(name: "Hoge", hp: hp) } } var character = Character(name: "ゆうしゃ", hp: 153) character.foo() print(character.name) // "Hoge"
(edited)
Avatar
omochimetaru 27-Feb-18 03:51 AM
あーそういうことか
03:51
self代入経由でのlet強制変更テクニックを無くせる
Avatar
lovee 27-Feb-18 03:53 AM
どうでもいいこと言いますと、サンプルコードとしては問題ないですが、ただ Character はそもそも値型ではなく参照型で作るべきなのでは?と思わなくもないですね
03:53
値型だと Character が代入されるたびにコピーされてしまうのでw
Avatar
koher 27-Feb-18 03:54 AM
↑を struct でやるのが僕の try! Swift のワークショップなのです😇
Avatar
lovee 27-Feb-18 03:55 AM
あとこの際、mutating funcとupdate func の区別をどうやって宣言で切り分けるのかも気になりますね…structですと、letで宣言するとnameもhpも変更できず、逆にvarで宣言するとどっちも結果として変更できる仕様になってしまいますので
Avatar
tarunon 27-Feb-18 03:56 AM
let var じゃたりない... const<おいすー^^
Avatar
koher 27-Feb-18 04:01 AM
@lovee ↓みたいなのをイメージしてます。 update は単語が微妙だったので replacing にしてみました。
struct Character { let name: String var hp: Int mutating func a() { self = Character(name: "Hoge", hp: hp) // NG } replacing func b() { self = Character(name: "Hoge", hp: hp) // OK } mutating func c() { self = Character(name: name, hp: 42) // NG hp = 42 // OK } replacing func d() { self = Character(name: name, hp: 42) // OK } }
(edited)
04:01
mutating replacing func もありです。
Avatar
lovee 27-Feb-18 04:02 AM
はい、それは問題なく理解できますが、ただきになるのは var character: Character の方の宣言ですね…
04:02
どうやって charactera()c() が呼べて b()d() が呼べない、もしくはその逆の保証をするのかですね…
Avatar
koher 27-Feb-18 04:03 AM
var character だと mutatingreplacing も呼べる想定ですね。 (edited)
Avatar
lovee 27-Feb-18 04:04 AM
はい、ですがその場合ですと mutatingreplacing の区別をする意味がなくなるのでは?というところです
Avatar
koher 27-Feb-18 04:04 AM
実装のわからない mutating func をコールした場合に let プロパティが書き換えられてしまうことがないことを保証できます。
Avatar
omochimetaru 27-Feb-18 04:04 AM
@lovee mutating func の中からは mutating func しか呼べない、replacing func の中では stored propery の var が変更できない、など、実装時の安全性が上がる
Avatar
koher 27-Feb-18 04:05 AM
また、これだと replacing funcclass でも使えます。
Avatar
lovee 27-Feb-18 04:05 AM
むしろ replacing は参照型限定にした方が実装の意味がある気がします 🤔
Avatar
omochimetaru 27-Feb-18 04:05 AM
それだと僕の案に近いですね
Avatar
lovee 27-Feb-18 04:06 AM
値型に replacing 導入しても、結局 var だとその実装が呼べる呼べない区別ができなくなってしまいますので
Avatar
koher 27-Feb-18 04:06 AM
うーん、↓を防ぎたいニーズはむしろ現実的にありそうな気がしています。再代入以外で let プロパティが書き換えられてるのって直感に反しませんか?
struct Character { let name: String var hp: Int mutating func foo() { self = Character(name: "Hoge", hp: hp) } } var character = Character(name: "ゆうしゃ", hp: 153) character.foo() print(character.name) // "Hoge"
04:07
replacing func を呼ぶ場合は &character.foo() とか特殊な構文にしてもいいかも?
Avatar
lovee 27-Feb-18 04:08 AM
@koher そのコードで防ぎたいことはわかりますが、ただ結果として値型ですとそもそも var 宣言使うと replacingmutating も使えるし、逆に let 宣言使うと replacingmutating も使えなくなって、区別ができなくなってしまうのが気になるポイントです
Avatar
koher 27-Feb-18 04:09 AM
なので、 replacing func の呼び出しは inout のように変化を付けたいですね。
Avatar
lovee 27-Feb-18 04:09 AM
値型に対して letvar 以外の第3の宣言が必要になってくると言語仕様がどんどん複雑に… 🤔
04:10
inout character: Character 的な宣言です?
04:10
あ違うか、inout letinout var にしないとですね 🤔
Avatar
koher 27-Feb-18 04:10 AM
いや、 &character.foo() 的な。
04:10
コール側ですね。
Avatar
lovee 27-Feb-18 04:11 AM
要はそれがコール側でもそもそも var じゃないと &character 使えないですね (edited)
Avatar
koher 27-Feb-18 04:11 AM
replacing func は使えないようにしたいけど mutating func は使いたいというニーズはほぼないと思うんですよね。
04:11
いや、あるかもしれないですが、それはまた別の話だと思います。
Avatar
omochimetaru 27-Feb-18 04:11 AM
@koher
extension Int { mutating func double() { self = self * 2 } } var i = 3 &i.double()
こう?
(edited)
Avatar
koher 27-Feb-18 04:12 AM
@omochimetaru そんな感じ。
04:12
だけど、
04:12
今は inoutmutating と等価だから、 & で被るのは微妙かも。
Avatar
omochimetaru 27-Feb-18 04:12 AM
僕は @lovee さんとは逆で、struct ユーザ側で replacing と mutating を分けるのは変な気がする
04:13
Int みたいな型を考えたときに、 self 全体変更と部分変更を区別して考えるのは
04:13
内部のデータ構造の実装詳細が露出してることになる
04:13
structは部分も全体も内部実装に隠蔽されているのが良い
04:13
classの場合は、「stored propery」の書き換えと、保持してる側のポインタの書き換え は、現状でも明確に区別が必要なことだからOK
Avatar
lovee 27-Feb-18 04:14 AM
@omochimetaru でもそもそも根本的な問題として、現状の仕様として let 宣言使う以外 &i を防ぐ手段がない、というのば私が言いたいことですね
Avatar
koher 27-Feb-18 04:14 AM
@lovee さんの replacing できないけど mutating できる第三の変数みたいなのもあり得るけど、それの意味するところは再代入できるけどプロパティの更新はできる変数と定数の中間のものを作りたいということになるから (edited)
04:15
それを検討する価値はあると思うんですが、 replacing func とは直交する話な気がします。
04:15
(結果的にそれが mutating 可と replacing 不可を実現するのであって、概念としては直交してる気がします。)
Avatar
lovee 27-Feb-18 04:28 AM
まあ @koher さんが言ってるのはプロパティーの再代入と自分自身の再代入を区別したい、という話はわかりますが、ただ現状値型の場合それが等価になってしまいますので、せいぜいソースコード上で i.foo() と書くか、&i.foo() とかくかの区別だけしかできない、というのが私の懸念点ですね
04:28
ですので @omochimetaru さんの主張で replacing を参照型だけのものにするか、もしくは値型にも replacing を導入するのあら、何らかの宣言レベルでの区別が欲しいというのが私の考えです
04:29
ただどっちもSwiftの仕様をさらに複雑化しているのが否めない感が 🙃
Avatar
koher 27-Feb-18 04:30 AM
↓これは let プロパティを更新する挙動をするので利用者を驚かせてしまうと思うんですが、
var character = Character(name: "ゆうしゃ", hp: 153) character.foo() print(character.name) // "Hoge"
↓これだと驚かないと思うんですよね。
var character = Character(name: "ゆうしゃ", hp: 153) character = Character(name: "Hoge", hp: character.hp) print(character.name) // "Hoge"
04:31
なので、 var 自体ができることをどうこうしたいというわけではなくて
04:31
メソッドコールのスタイルで let プロパティが書き換えられてしまうことを防ぎたいということです。
Avatar
tarunon 27-Feb-18 04:32 AM
letに関しては一番外側がletじゃなければ大して意味ないよなというのは気づいて理解してるつもりだけど
04:32
わからないとわからないのか。
04:32
04:32
理解してないと混乱してしまうのか
Avatar
koher 27-Feb-18 04:32 AM
なので &character.foo() のようにコール時に明示的な区別がされれば OK だと思います。
Avatar
omochimetaru 27-Feb-18 04:33 AM
@tarunon 自分の直感がローレイヤのメモリモデルの方にあるから自分は驚かないけど、人によるのかなと思った。
Avatar
koher 27-Feb-18 04:33 AM
似たようなことは inout ですでに行われていて、もし↓のコードが & なしでコールできたらユーザーを驚かせてしまうと思うんですね。
var a = 2, b = 3 swap(&a, &b) print(a) // 3 print(b) // 2
Avatar
lovee 27-Feb-18 04:34 AM
なので &character.foo() のようにコール時に明示的な区別がされれば OK だと思います。
それを突き詰めると、そもそも値型でメソッドを呼んだら自分自身のプロパティーが変わった、ということ自体も明確にして欲しいという欲求が出てきてしまいそうな気が… 🙃
Avatar
koher 27-Feb-18 04:35 AM
プロパティを変えられるかどうかはプロパティを var で宣言するか let で宣言するかで区別しているので
04:35
var のプロパティが変更されることは当然あり得ると思うんですが、 let のプロパティが変更されるのは直感に反しませんか?
Avatar
omochimetaru 27-Feb-18 04:36 AM
letのプロパティが変更されてるんじゃなくて、letのプロパティを持つ struct 全体が差し替わっている
04:36
結果的に、そのletの場所が変わったようにも見える(同一視できる)
Avatar
koher 27-Feb-18 04:36 AM
僕も前は↓の意見でしたが、ちょっと意見が変わってきています。 https://qiita.com/omochimetaru/items/7265e440418b38088ccb
# 記事について この記事は potatotips#39 という勉強会で発表した内容を再掲したものです。スライドの画像と、喋った言葉を載...
Avatar
omochimetaru 27-Feb-18 04:37 AM
struct全体が可変であることはstructを持ってるvar側で表明してること
Avatar
koher 27-Feb-18 04:37 AM
メモリ上の挙動を考えればその通りだけど、
04:38
その考え方でいくと、せっかく言語が提供している( struct のプロパティで) varlet かを区別する機能を殺してると思うんですね。
Avatar
tarunon 27-Feb-18 04:39 AM
大事なのは一番外側がletかvarかで
04:39
内側は大してアテにならない
Avatar
omochimetaru 27-Feb-18 04:39 AM
init経由するときに制約がかけられるという実装側での意味がありますね
04:40
structのプロパティでletにできる意味。それ以外は無意味。
Avatar
tarunon 27-Feb-18 04:40 AM
initでvalidationした値はletに入れると安全とかありますね、確かに
Avatar
omochimetaru 27-Feb-18 04:40 AM
たとえletであっても、ユーザー側でextensionを使ってsetterを生やせる。ただし、そのsetterの実現にあたってinitを経由する制約だけは残る。
04:41
原則の意見は↑のスライドと変わってないけど、考慮すべき例外条項がなんなのか、という点については考え続けていて、↑に至った。
Avatar
koher 27-Feb-18 04:42 AM
mutating funcreplacing func を分ければ「たとえletであっても、ユーザー側でextensionを使ってsetterを生やせる。」も同じものは提供できなくなります。 replacing func のコールで & 必須だと。
Avatar
omochimetaru 27-Feb-18 04:43 AM
ですね
Avatar
lovee 27-Feb-18 04:44 AM
まあ確かに i.foo() より &i.foo() の方がわかりやすい、というのはわかりますが、そこまでやるならやはり inout var i 宣言が欲しいかな、と思います
04:45
でないとせっかく目立つものを作ったのにコンパイルレベルで保証できないってのはなんか悲しい (edited)
Avatar
koher 27-Feb-18 05:05 AM
そうですね〜。僕も自分の言ってることが本当に意味のある区別なのかイマイチ確信が持ててないですが、直感的に意味がある気がしています。いい例を思い付いたらまた書きますね🙂
Avatar
hironytic 27-Feb-18 06:51 AM
i += 1 // i = i + 1
だから、
i.=foo() // i = i.foo()
とか(いや、やりたいことと違う)。
Avatar
tarunon 27-Feb-18 06:51 AM
例えば参照が古き良き ->だったら (edited)
06:52
i=>foo() // i = i -> foo() とかワンチャンあったかも(ない)
Avatar
norio_nomura 01-Mar-18 05:16 AM
Swift 4.1でメソッドオーバーロードの判定が賢くなってた。
protocol P1 { init() } protocol P2 { init() } struct S { func a<T: P1>(_ type: T.Type) -> T { return a(type) ?? type.init() } private func a<T>(_ type: T.Type) -> T? { guard let p2Type = type as? P2.Type else { return nil } return p2Type.init() as? T } } extension Int: P1 {} S().a(Int.self) // Swift 4.1より前は無限ループ
Avatar
tarunon 01-Mar-18 05:31 AM
4.1、型推論も賢くなってますね
Avatar
omochimetaru 01-Mar-18 04:02 PM
funcのaが<T: P1>で、private funcのaが<T>で・・・、
16:03
無限ループしないってことは、上のaの中で呼んでるaはprivateの方が呼び出されるってことですか?
16:04
上のaの中で呼んでるaも、上のaになるのが正しいと思いました、制約がキツイ方を優先するから。何か見落としてる??
Avatar
rintaro 01-Mar-18 04:25 PM
Optional<T> 期待になるから private 側が呼び出されてるってことっぽい。
Avatar
omochimetaru 01-Mar-18 04:35 PM
あ〜、??の左辺だからか。ということは、4.0では、 T に推論した上で Optional<T> への暗黙のアップキャストが推論されるアレだったのが、変わったということですか!
16:48
手元の4.0環境だと
(inject_into_optional implicit type='T?' location=a.swift:12:16 range=[a.swift:12:16 - line:12:22] (call_expr type='T' location=a.swift:12:16 range=[a.swift:12:16 - line:12:22] nothrow arg_labels=_:
16:49
a(type) のところの call_exprがTで、その一個上に inject_into_optional があるからそうっぽい
16:49
4.1だと inject_into_optionalが無くて call_exprが T? になっているのかな。
Avatar
omochimetaru 01-Mar-18 05:12 PM
[omochi@omochi-MB2 infer]$ export TOOLCHAINS=org.swift.3020180227a [omochi@omochi-MB2 infer]$ swift --version Apple Swift version 4.1-dev (LLVM c4ec2ab808, Clang af436f313e, Swift 5f2f440067)
17:12
snapshot 2/27の4.1で試したけど同じように落ちた・・・
Avatar
omochimetaru 01-Mar-18 11:07 PM
@norio_nomura#8334 試した4.1はどれですか?
Avatar
norio_nomura 01-Mar-18 11:16 PM
Xcode 9.3 beta 3のPlaygroundもswift-4.1-DEVELOPMENT-SNAPSHOT-2018-02-28-aのREPLも落ちないです。 (edited)
Avatar
omochimetaru 01-Mar-18 11:17 PM
あれ〜 会場ついたら改めてやってみます。
Avatar
tarunon 02-Mar-18 12:25 AM
↑普通に動いた。おもちのXcode壊れてるんやない?
00:28
↑なんか違う?
Avatar
tarunon 02-Mar-18 12:32 AM
昨日のDev版が壊れた?
Avatar
norio_nomura 02-Mar-18 12:35 AM
それはswift-DEVELOPMENT-SNAPSHOT-2018-02-27-aですね。
00:36
masterのスナップショット。
00:39
swift-4.1-branchのスナップショットならorg.swift.3020180227aではなくorg.swift.4120180227aなはず。
Avatar
omochimetaru 02-Mar-18 12:42 AM
そっちもやってみます!
Avatar
omochimetaru 02-Mar-18 01:15 AM
あ〜いけました org.swift.4120180228a だと実行できた。
01:18
(call_expr type='T?' location=a.swift:12:16 range=[a.swift:12:16 - line:12:22] nothrow arg_labels=_:
01:18
予想通り式自体が aのT がT? で推論されて、暗黙キャストが無くなった (edited)
01:19
推論候補探索の優先度付けが変わったって事かな
Avatar
koher 05-Mar-18 08:40 AM
Data の↓の引数が UnsafeRawBufferPointer じゃないのってなんでなんですっけ?
init(bytes: UnsafeRawPointer, count: Int)
https://developer.apple.com/documentation/foundation/data/1780158-init
(edited)
Avatar
rintaro 05-Mar-18 08:42 AM
Avatar
koher 05-Mar-18 08:43 AM
でもわざわざ NSData とは別に Data を作ったわけで、 RawBuffer でもよかった気がするんですがいかがでしょう?
08:44
もしかして、 Data の導入とポインタ系の整理のタイミング問題でそうなってしまったとか?
Avatar
rintaro 05-Mar-18 08:45 AM
UnsafeRawBufferPointer 版が無いのは UnsafeRawBufferPointer が出てきたときに Data 側対応が漏れているだけだと思います。
Avatar
koher 05-Mar-18 08:45 AM
なるほど。
08:47
じゃあ、これと↓に Buffer 版を追加しようという提案はあり得そうですね。 https://developer.apple.com/documentation/foundation/data/1780455-init
Avatar
rintaro 05-Mar-18 08:48 AM
アリだと思います!
🙂 1
Avatar
rintaro 05-Mar-18 08:55 AM
さくっと https://github.com/apple/swift-evolution/blob/master/proposals/0138-unsaferawbufferpointer.md の addendum としてフルプロセス通さずに実装される可能性もありそう。
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
koher 05-Mar-18 08:59 AM
なるほど。どちらにしても一度 evolution に pitch として投げてみると良さそうですね。
👍 1
Avatar
koher 05-Mar-18 09:29 AM
これはバグでしょうか?多分 [array] が再現のポイントです。それがなければ通ります。
func foo<R, T>( array: [T], operation: (Int) throws -> R ) rethrows -> R { return try array.withUnsafeBytes { [array] _ in return try operation(array.count) } }
error: repl.swift:5:16: error: call can throw, but the error is not handled; a function declared 'rethrows' may only throw if its parameter does return try array.withUnsafeBytes { [array] _ in ^ repl.swift:5:38: note: call is to 'rethrows' function, but argument function can throw return try array.withUnsafeBytes { [array] _ in ^
(edited)
Avatar
rintaro 05-Mar-18 09:42 AM
それがなければ通ります。
手元環境 Xcode Version 9.2 (9C40b) だと error: overlapping accesses to 'array', but modification requires exclusive access; consider copying to a local variable です。
(edited)
09:43
いずれにしてもこのエラー(call can throw, ...)はバグっぽい。 (edited)
Avatar
koher 05-Mar-18 09:44 AM
探してみて類似のものがなければレポートしておきます🙂 (edited)
Avatar
koher 05-Mar-18 10:03 AM
@rintaro
手元環境 Xcode Version 9.2 (9C40b) だと
↑のコード、投稿後すぐに修正したんですが、コード修正前じゃないでしょうか? https://wandbox.org/ で Swift HEAD 4.2-dev だと [array] なくせば通りました。
Avatar
rintaro 05-Mar-18 10:04 AM
おー、そうだったみたいです。9C40b で通りました。
🙏 1
Avatar
koher 05-Mar-18 10:09 AM
レポートしました。実は初めてな気がする・・・。 https://bugs.swift.org/browse/SR-7120
🎉 3
Avatar
omochimetaru 08-Mar-18 05:08 AM
Hi, I am thinking about writing a Protocol Devirtualizer Pass that specializes functions that take Protocols as arguments to transform them with concrete types instead of protocol types when the concrete types can be determined statically by some compiler analysis. This is the first step of the transformation that I am proposing. My goal is to extend this to eliminate the original function implementation and also to remove the corresponding protocol type (by deleting it from the witness t...
05:09
@ukitaka ↑プロトコル devirtualize の最適化の実装の話し合いのスレがあった。 フォーラムでアルゴリズムの相談してからPR出す、みたいなのもあるんですね
Avatar
ukitaka 08-Mar-18 05:30 AM
おー、specializeされてるなら具体型が静的にわかるから最適化できるってことかな、まさにこの前話してたようなやつっすね!
Avatar
omochimetaru 08-Mar-18 05:32 AM
(まだ詳細は見てないので後で見ます)
Avatar
ukitaka 08-Mar-18 05:36 AM
もう実装もあるんですね https://github.com/apple/swift/pull/13991
Protocol Devirtualizer Pass that specializes functions that take Protocols as arguments to transform them with concrete types instead of protocol types when the concrete types can be determined sta...
Avatar
kitasuke 08-Mar-18 07:51 AM
これは面白い。PR単位なら何となくわかる気がした
Avatar
omochimetaru 13-Mar-18 02:00 AM
swift - The Swift Programming Language
02:01
Array.withUnsafeMutableBufferPointerがbodyにinout UnsafeMutableBufferPointerを渡すんだけど
02:01
defer { _precondition( inoutBufferPointer.baseAddress == pointer && inoutBufferPointer.count == count, "${Self} withUnsafeMutableBufferPointer: replacing the buffer is not allowed") (work, self) = (self, work) }
02:01
inoutを用いて書き換わってるとエラーになる。
Avatar
koher 13-Mar-18 02:02 AM
チャネル変わってない?
Avatar
omochimetaru 13-Mar-18 02:02 AM
話題分けた
Avatar
koher 13-Mar-18 02:02 AM
なるほど。
02:02
これって単に「 inoutout を除いたもの」として、 @escaping なクロージャにキャプチャされるのを防ぐために使われてるのかな?
02:03
そうだとしても、 withUnsafeBufferPointer がそうなってないのが謎だけど。
02:16
元は、保持するバッファそのものを書き換え可能なAPIだったぽい。
Avatar
koher 13-Mar-18 02:18 AM
元は、保持するバッファそのものを書き換え可能なAPIだったぽい。
ヤバげな感じだしますね・・・。
Avatar
omochimetaru 13-Mar-18 02:18 AM
This results in a a massive speedup and could in principle be applied to other bulk array mutations. Swift SVN r18926
02:19
僕もやっとinoutがついた瞬間のコミットに辿りついた (edited)
Avatar
norio_nomura 13-Mar-18 02:26 AM
そっちの方がそれっぽいか。どちらにしろ、もうinoutじゃなくても良さそうだけど、escapingに渡すのを防げてるのは好都合ですね。
02:31
withUnsafe*Pointer系は全部そうなってても良い気がする。
Avatar
koher 13-Mar-18 02:33 AM
ですよね。 withUnsafeMutableBufferPointer だけそうなのがよくわからない。
02:34
そして、ポインタ自体の書き換えを禁止するなら、やっぱり inoutout なし版( @escaping に渡すのを防ぐだけ)がほしい。
Avatar
もあい 16-Mar-18 11:33 AM
たまたま見つけたんですが
import UIKit protocol SomeChild where Self : UIViewController { func doSomething() } extension SomeChild { func doSomething() { print(self.title) } } class ChildViewController: UIViewController, SomeChild {} class ParentViewController: UIViewController { var children: [SomeChild] = [ChildViewController()] var child: SomeChild = ChildViewController() } let parent = ParentViewController() parent.child.doSomething() parent.children.forEach { $0.doSomething() }
childにアクセスすると問答無用でEXC_BAD_ACCESSになる
11:34
extension側に where句 付けると問題なし
protocol SomeChild { func doSomething() } extension SomeChild where Self : UIViewController { func doSomething() { print(self.title) } }
Avatar
tarunon 16-Mar-18 11:37 AM
オッこれは…
11:39
Existentialが壊れてるじゃないですか!大好物です
😱 2
Avatar
Kishikawa Katsumi 16-Mar-18 11:39 AM
EXC_BAD_ACCESSって理由はStackoverflowですか?
11:40
違うな。
Avatar
tarunon 16-Mar-18 11:40 AM
witness tableの実装からobjc_msgSend見てて
11:41
Selector見つからないからホゲホゲになってる気がする
11:45
Xcodeがしんだ
Avatar
もあい 16-Mar-18 11:46 AM
OjbC起因かとも思い試しにLinux版でも試すとBAD_ACCESSでますね
class Object {} protocol SomeChild where Self : Object { func doSomething() } extension SomeChild { func doSomething() { print(self) } } class ChildObject: Object, SomeChild {} class ParentObject: Object { var children: [SomeChild] = [ChildObject()] var child: SomeChild = ChildObject() } let parent = ParentObject() parent.child.doSomething() parent.children.forEach { $0.doSomething() }
Avatar
tarunon 16-Mar-18 11:47 AM
Existentialなのかwitnessなのか問題を切り分けるのに
Avatar
omochimetaru 16-Mar-18 11:47 AM
existentialに入れてる事とSelf制約の2点かな?
Avatar
tarunon 16-Mar-18 11:47 AM
Generics実装作ったらそっちは動いた
11:47
import UIKit protocol SomeChild where Self : UIViewController { func doSomething() init() } extension SomeChild { func doSomething() { print(self.title as Any) } } class ChildViewController: UIViewController, SomeChild {} class ParentViewController<C: SomeChild>: UIViewController { var children: [C] = [C()] var child: C = C() } let parent = ParentViewController<ChildViewController>() parent.child.doSomething() parent.children.forEach { $0.doSomething() }
11:48
クラス制約プロトコルのExistentialが壊れていて、witnesstableからobjcランタイムを参照して死
11:48
と言う流れな気がしたがーもうちょい
Avatar
omochimetaru 16-Mar-18 11:49 AM
モアイさんがLinuxで再現してるからオブシーは関係ないかと
Avatar
tarunon 16-Mar-18 11:49 AM
デフォルト実装である必要はない
class Object {} protocol SomeChild where Self : Object { func doSomething() } class ChildObject: Object, SomeChild { func doSomething() { print("hello") } } class ParentObject: Object { var children: [SomeChild] = [ChildObject()] var child: SomeChild = ChildObject() } let parent = ParentObject() parent.child.doSomething() parent.children.forEach { $0.doSomething() }
11:50
class Object {} protocol SomeChild where Self : Object { func doSomething() } class ChildObject: Object, SomeChild { func doSomething() { print("hello") } } let c: SomeChild = ChildObject() c.doSomething() // 😇
11:50
最小コードはここかな
11:50
クラス制約プロトコルのExistentialは壊れていてメソッドを呼び出せません!完
11:51
報告しよう @moaible
Avatar
もあい 16-Mar-18 11:51 AM
な、なるほどJIRAにチケット登録すれば良いんでしたっけ?
Avatar
tarunon 16-Mar-18 11:51 AM
Yes!
11:52
ん?なんかそもそも変だぞ
11:52
class Object { var x: Int = 1 } protocol SomeChild where Self : Object { func doSomething() } class ChildObject: Object, SomeChild { func doSomething() { print("hello") } } let c: SomeChild = ChildObject() c.x // Compile Error c.doSomething()
SomeChildはObjectを満たしているはずだが、xを呼び出せない
11:53
Existentialだからか?でもこれは…
Avatar
norio_nomura 16-Mar-18 11:53 AM
let c: SomeChild & Object = ChildObject()
って書くと動く。
Avatar
tarunon 16-Mar-18 11:54 AM
ですね
Avatar
rintaro 16-Mar-18 11:55 AM
protocol SomeChild where Self : AnyObject { func doSomething() } class ChildObject: SomeChild { func doSomething() { print("hello") } } let c: SomeChild = ChildObject() c.doSomething()
最小これか。まあこれは protocol SomeChild: AnyObject { って書けば良いじゃんて話ですが。
11:55
とにかくバグはバグだと思いますね。
Avatar
tarunon 16-Mar-18 11:56 AM
これSelf:AnyObject:AnyObjectで動き変わるんすね
11:56
前者は__SwiftObjectということになってるのかな
11:56
後者はclass
Avatar
rintaro 16-Mar-18 11:57 AM
witness テーブル 読みにいってるんだけど実際は vtable でした、か、逆か。
11:58
そんな感じのことが起こってる気がする。
Avatar
tarunon 16-Mar-18 11:58 AM
class前提プロトコルをextensionした時に
Avatar
norio_nomura 16-Mar-18 11:58 AM
TYPE MISMATCH IN ARGUMENT 0 OF APPLY AT expression at [<REPL>:12:1 - line:12:15] RangeText="c.doSomething()" argument value: %13 = open_existential_addr immutable_access %6 : $*SomeChild to $*@opened("25C7E87E-2911-11E8-A83E-0242AC110002") SomeChild // user: %14 parameter type: $@opened("25C7E87E-2911-11E8-A83E-0242AC110002") SomeChild
Avatar
tarunon 16-Mar-18 11:58 AM
本来witness-tableに行くはずのものがvtableに乗ってるみたいな (edited)
11:58
そういうのが有り得そう
Avatar
norio_nomura 16-Mar-18 12:00 PM
protocol … where Self: …っていう書き方、最近まで知らなかった。
Avatar
tarunon 16-Mar-18 12:00 PM
ひらりぷろとこる
12:01
あーーー
12:01
この間ですね、この記法のプロトコル使ってバグふんでたんですが、最小コード見つけられなくて諦めてたのがある
12:01
もしかしたらこれ参考にすれば最小見つかるかもしれない
12:02
雰囲気は、制約をすべて満たしたはずなのにコンパイルが通らなくなる感じです。
Avatar
もあい 16-Mar-18 12:25 PM
とりあえず作りました、こんな感じで良かったのか... https://bugs.swift.org/browse/SR-7214
👏 5
Avatar
omochimetaru 16-Mar-18 12:32 PM
This code crashes. But this code works. の方が良いと思う。
🙏 1
12:32
あと、タイトルの文字列が何をやると出るものなのか説明したほうがよし
12:32
(コマンドライン
🙆 1
Avatar
tarunon 16-Mar-18 12:33 PM
class制約付きprotocolのexistentialが一般に壊れてる事がわかった方がいいかも
🙆 1
Avatar
koher 19-Mar-18 08:12 AM
Swift 4.1 でも Optional: Hashable where Wrapped: Hashable になってないみたいですがなぜでしょう?
Avatar
omochimetaru 19-Mar-18 08:17 AM
Optional : Equatable とか Array : Hashsable はなってるんですっけ?
Avatar
rintaro 19-Mar-18 08:20 AM
https://github.com/apple/swift/pull/14527 まだマージされてないです。
As a followup to SE-0143, this adds conditional conformance to Hashable to the following types in the standard library: Optional Array, ContiguousArray, ArraySlice Dictionary Range, ClosedRange An...
💡 1
Avatar
koher 19-Mar-18 08:22 AM
お、なるほど。 Equatable はもう実装されてるようなので、もし Hashable も同じようにするならもう実装済みだろうと思いこんでました。
Avatar
omochimetaru 20-Mar-18 05:34 AM
func makeFunc<A, R>(argType: A.Type, returnType: R.Type, body: @escaping (A) -> R) -> (A) -> R { return body } makeFunc(argType: Int.self, returnType: String.self) { String($0) }(3) makeFunc(argType: (Int, Int).self, returnType: (String, String).self) { (String($0.0), String($0.1)) }((1, 2)) makeFunc(argType: Void.self, returnType: Void.self) { _ -> Void in print(33) }(()) // error makeFunc(argType: ().self, returnType: Void.self) { _ -> Void in print(33) }(()) // error makeFunc(argType: Void.self, returnType: ().self) { _ -> Void in print(33) }(()) print( ().self is Void.Type ) // false print( Void.self is ().Type ) // true
05:34
()Void は違うものだった?
Avatar
t.ae 20-Mar-18 05:36 AM
print(().self is ().Type) // false print(Void.self is Void.Type) // true
❗ 1
05:36
()の扱いが特殊そう?
Avatar
hiragram 20-Mar-18 05:37 AM
()はVoidのインスタンスとしても使えるらへんになんかありそう
Avatar
omochimetaru 20-Mar-18 05:37 AM
たしかに。Void は型だけで値に使えないし。
Avatar
rintaro 20-Mar-18 05:39 AM
print(().self is ()) // true
Avatar
t.ae 20-Mar-18 05:40 AM
print(().self == ()) // true
何だこれは
Avatar
omochimetaru 20-Mar-18 05:41 AM
// error だけど 引数のところは許された・・・ makeFunc(argType: (), returnType: ()) { _ in print(33) }(())
Avatar
rintaro 20-Mar-18 05:42 AM
expression が許されている箇所で () を型としては扱えないようです。
05:42
let a = [()]() // error
Avatar
omochimetaru 20-Mar-18 05:44 AM
値の () と 型の () があるのか
Avatar
rintaro 20-Mar-18 05:47 AM
swift - The Swift Programming Language
Avatar
omochimetaru 20-Mar-18 05:47 AM
FIXMEだ
Avatar
t.ae 20-Mar-18 05:48 AM
()が型である必要って今何かあるんですっけ? 前は()->Voidで必要でしたけど (edited)
Avatar
omochimetaru 20-Mar-18 05:50 AM
この関数おもしろいな
Avatar
rintaro 20-Mar-18 05:50 AM
(Int) -> () 型を禁止するわけにはいかないからでしょうか。
Avatar
omochimetaru 20-Mar-18 05:50 AM
// Fold 'P & Q' into a composition type if (auto *binaryExpr = dyn_cast<BinaryExpr>(E)) {
05:51
最初は演算子の&で来るんやね
Avatar
rintaro 20-Mar-18 05:51 AM
この関数おもしろいな
この関数泥臭くて大好き。
😄 1
Avatar
t.ae 20-Mar-18 05:51 AM
右辺はもうVoidでいいと言うかもともと()->()みたいな書き方しなかったですね……
Avatar
tarunon 20-Mar-18 05:51 AM
TypeCheckウッ
05:52
そういえばObjCとの兼ね合いは、そもそもObjC関数に二重Optionalは実装出来ないからoverrideしようとしたらそこでエラーが出てコンパイルできないので結果としては問題なさそうな雰囲気だった。大統一実装は難しくて手こずってる
05:52
↑二重Optional override問題の話
Avatar
omochimetaru 20-Mar-18 05:53 AM
overrideできる型変換は親クラスがObjCだったときでも大丈夫な変換だけに制限されているってこと?
Avatar
tarunon 20-Mar-18 05:54 AM
@objcな関数や変数をoverrideすると、overrideしたそれも@objcの扱いになっているっぽくて
05:55
@objcではネストしたOptionalは許可されないので、コンパイルエラーになる
Avatar
omochimetaru 20-Mar-18 05:55 AM
二重Optionalのオーバライド禁則は純粋なSwiftクラスでも駄目なのはobjcに引っ張られてる?
Avatar
tarunon 20-Mar-18 05:56 AM
いやそこは普通のSubtypingとoverrideの実装が別れてて、片方は未実装だっただけなんだと思う
05:56
実装追加した例のPRでは全部のテストケースがパスしていて
Avatar
omochimetaru 20-Mar-18 09:29 AM
I would like to propose the elimination of the Review phase of the evolution proposals. Instead I propose the Core team to discuss privately and announce the decision for each proposal. Motivation The Review phase gives the false impression of a...
09:29
「レビューフェーズやめてコアチームで話し合って結論出して」スレ
Avatar
lovee 20-Mar-18 09:35 AM
言いたいこと分からなくもないけどとりあえずラトナーの返事にハートつけといた
Avatar
omochimetaru 20-Mar-18 09:36 AM
わかる
Avatar
Kishikawa Katsumi 20-Mar-18 10:27 AM
まあうまくバランスをとって運営しないといけないので難しいんだけど今のところ私は必要なコストだと思います。もっとSwiftが広く多くの人にいろいろな場面で使われるようになったらまた違う意見を持つかも。
Avatar
tarunon 20-Mar-18 10:28 AM
いろいろなフェーズがあって、例えばABI安定化する前と後とかそういう重要なタイミングで適切なレビューフローも変わってくると思う
Avatar
takasek 21-Mar-18 04:15 AM
そもそもVoidって空タプルのtypealiasじゃなかったですっけ 今違う?
Avatar
rintaro 21-Mar-18 04:17 AM
そのはずですよ。
Avatar
hiragram 21-Mar-18 04:23 AM
そうだったのか、しらなかった
04:23
だから()は型にも値にもなる、なるほど。
Avatar
rintaro 21-Mar-18 04:28 AM
あー、いや正確には ()型 の typealias であって、()値 と ()型 は違います。
Avatar
hiragram 21-Mar-18 04:29 AM
let hoge: () って書けましたっけ?
Avatar
rintaro 21-Mar-18 04:29 AM
yes
Avatar
hiragram 21-Mar-18 04:29 AM
かけるのか
Avatar
tarunon 21-Mar-18 05:12 AM
tupleの値の表記が(1, 2)で、型の表記が(Int, Int)なのだが、これが空になるとどちらも()になるので混乱する
Avatar
tarunon 22-Mar-18 03:31 AM
let void: Void = ()って書いておいて、型ならVoid、値ならvoidを使うようにすれば楽になりそうだと一日考えて思った。
Avatar
takasek 22-Mar-18 04:25 AM
let void = () func xxx() -> Void { return void }
こういうことです? グローバルにあるのも違和感なので
extension Void { static var void: Void = () } func xxx() -> Void { return .void }
こんなかんじですかね(extensionかけないけど)
Avatar
tarunon 22-Mar-18 04:34 AM
よさそう
04:34
voidはGlobalでも良いかなとは思います
04:35
let void: Void = () func nop<T>(_ arg: T) { } func undefined<T>() -> T { preconditionFailure() }
この辺大好き
(edited)
Avatar
t.ae 22-Mar-18 04:35 AM
(型の()を排除する方向に持っていくほうが筋が良い気がする)
Avatar
tarunon 22-Mar-18 04:36 AM
型排除だけならSwiftLintがデフォで入ってて、Voidにしろ君がいたはず
Avatar
rintaro 22-Mar-18 04:36 AM
let () : () = ()
😇 5
04:36
パターンもアルヨ
Avatar
tarunon 22-Mar-18 04:37 AM
Tupleの変数宣言時の分解と型と値の3パターンだ
Avatar
omochimetaru 22-Mar-18 04:37 AM
www
Avatar
tarunon 22-Mar-18 04:38 AM
分解先が0個だから意味は無いけどコンパイルは通る
Avatar
t.ae 22-Mar-18 04:38 AM
let () : Void = ()
04:38
destructuring assignmentなのかとおもったけどこれでも通る……
Avatar
t.ae 22-Mar-18 04:47 AM
let (a): Int = (0)
これが通るから不自然ではないか。
(edited)
🙄 1
Avatar
tarunon 22-Mar-18 08:06 AM
めっちゃ面白い事に気がついた
protocol Foo { } struct FooStruct: Foo { } protocol FooProtocol: Foo { } protocol Bar { func accept(_ foo: FooStruct) func accept<X>(_ foo: X) where X: FooProtocol } class BarImpl: Bar { func accept<X>(_ foo: X) where X: Foo { } }
08:06
このコンパイルが通る
08:06
protocolで定義されたoverloadをprotocolのimplのタイミングで共通化できる、すごい (edited)
Avatar
koher 22-Mar-18 08:10 AM
なんか色々と問題を引き起こしそうな・・・
08:10
広げて包含してるだけだから問題ないかなぁ・・・。
Avatar
tarunon 22-Mar-18 08:11 AM
問題は無いですね
08:11
Witnesstableが問題なければ
Avatar
tarunon 22-Mar-18 08:19 AM
↑これGenericsがマッチするのはOKだけど、Existentialにまで膨らまして解決できるものじゃなかったので
08:19
TC.subtype周りじゃないところで解決されてるっぽいことが想像出来る
08:25
Subclassもダメなので、Generics周りかな
08:27
仕様じゃなくて偶然の産物、つまり半分バグの可能性もあるな
Avatar
koher 22-Mar-18 08:32 AM
ジェネリクス関係なくできた。色々いじってる間にジェネリクスになってた😅
protocol Root {} protocol Foo : Root {} protocol Bar : Root {} protocol A { func accept<F : Foo>(_ foo: F) func accept<B : Bar>(_ bar: B) } extension A { func accept<F : Foo>(_ foo: F) { print("Foo: \(foo)") } func accept<B : Bar>(_ bar: B) { print("Bar: \(bar)") } } class B : A { func accept<R : Root>(_ root: R) { print("Root: \(root)") } } struct FooImpl : Foo {} struct BarImpl : Bar {} B().accept(FooImpl()) B().accept(BarImpl())
(edited)
08:34
↓これはエラー
protocol Root {} protocol Foo : Root {} protocol Bar : Root {} class A { func accept<F : Foo>(_ foo: F) { print("Foo: \(foo)") } func accept<B : Bar>(_ bar: B) { print("Bar: \(bar)") } } class B : A { override func accept<R : Root>(_ root: R) { print("Root: \(root)") } } struct FooImpl : Foo {} struct BarImpl : Bar {} B().accept(FooImpl()) B().accept(BarImpl())
08:36
お、ジェネリクスじゃなくてもできた。
protocol Root {} protocol Foo : Root {} protocol Bar : Root {} protocol A { func accept(_ foo: Foo) func accept(_ bar: Bar) } extension A { func accept(_ foo: Foo) { print("Foo: \(foo)") } func accept(_ bar: Bar) { print("Bar: \(bar)") } } class B : A { func accept(_ root: Root) { print("Root: \(root)") } } struct FooImpl : Foo {} struct BarImpl : Bar {} B().accept(FooImpl()) // Root: FooImpl() B().accept(BarImpl()) // Root: BarImpl()
(edited)
08:37
あれ?
08:38
ダメだった。
let a: A = B() a.accept(FooImpl()) // Foo: FooImpl() a.accept(BarImpl()) // Bar: BarImpl()
08:40
あー、デフォルト実装付けてわかりづらくなってただけだった・・・
08:40
accept がジェネリックだったらちゃんとオーバーライドできてた。
08:41
Existentialにまで膨らまして解決できるものじゃなかったので
の通りだった。
Avatar
ukitaka 22-Mar-18 08:41 AM
そもそもこういうオーバーライドができるんですね。。 しかも広げるほうも狭めるほうもできてしまうぞ。。
protocol Root {} protocol Foo : Root {} // 1 class A { func accept<R : Root>(_ root: R) { } } class B : A { override func accept<R : Foo>(_ root: R) { } } // 2 class A2 { func accept<R : Foo>(_ root: R) { } } class B2: A2 { override func accept<R : Root>(_ root: R) { } }
Avatar
koher 22-Mar-18 08:42 AM
え、狭める方どうなってるんでしょう??
Avatar
ukitaka 22-Mar-18 08:44 AM
なんか...普通に壊れている気がしますね 😅
Avatar
koher 22-Mar-18 08:45 AM
やば、バグでは
protocol Root {} protocol Foo : Root {} // 1 class A { func accept<R : Root>(_ root: R) { } } class B : A { override func accept<R : Foo>(_ root: R) { } } // 2 class A2 { func accept<R : Foo>(_ root: R) { } } class B2: A2 { override func accept<R : Root>(_ root: R) { } } struct RootImpl : Root {} struct FooImpl : Foo {} let b: B = B() // b.accept(RootImpl()) // コンパイルエラー let a: A = b a.accept(RootImpl()) // OK
(edited)
08:48
↓ヤバすぎww
protocol Root {} protocol Foo : Root { func foo() } // 1 class A { func accept<R : Root>(_ root: R) { } } class B : A { override func accept<R : Foo>(_ root: R) { root.foo() } } // 2 class A2 { func accept<R : Foo>(_ root: R) { } } class B2: A2 { override func accept<R : Root>(_ root: R) { } } struct RootImpl : Root {} struct FooImpl : Foo { func foo() { print("foo") } } let b: B = B() // b.accept(RootImpl()) // コンパイルエラー let a: A = b a.accept(RootImpl()) // 実行時エラー
08:50
master からビルドした最新の swift でもダメだった。。。 (edited)
Avatar
omochimetaru 22-Mar-18 09:24 AM
protocol AnimalProtocol { func speak() -> String } protocol CatProtocol : AnimalProtocol { func nya() -> String } class AnimalEater { func accept<X : AnimalProtocol>(_ x: X) {} } class CatEater : AnimalEater { override func accept<X : CatProtocol>(_ x: X) { print(x.nya()) } } class Dog : AnimalProtocol { func speak() -> String { return "bow wow" } } let catEater = CatEater() let animalEater = catEater as AnimalEater let dog = Dog() animalEater.accept(dog) // file:///Users/omochi/work/playground/iOSGround.playground: error: Playground execution aborted: error: Execution was interrupted, reason: EXC_BAD_ACCESS (code=1, address=0x0). // The process has been left at the point where it was interrupted, use "thread return -x" to return to the state before expression evaluation.
(edited)
09:25
あらあら
Avatar
tarunon 22-Mar-18 09:25 AM
戻ってきたらめっちゃおもろいことになってた
Avatar
omochimetaru 22-Mar-18 09:25 AM
随分前に @norio_nomura が、override判定のところでwhere句の考慮がおかしいの見つけてたけど、それがまだ壊れてるっぽい
🤔 1
Avatar
norio_nomura 22-Mar-18 09:40 AM
今日調べてたStringProtocol.hasPrefix(_:)が似た状況かも。 https://github.com/apple/swift/commit/f9b3e14137ac2f50e93aa2c1db28511e05f88e75
…14390) * Use Swift-native Character iteration for hasPrefix/Suffix * Remove old tests for removed C shims
09:41
requirementが
public protocol StringProtocol … { … func hasPrefix(_ prefix: String) -> Bool
で、実装が
extension StringProtocol { … public func hasPrefix<Prefix: StringProtocol>(_ prefix: Prefix) -> Bool {
になってる。
(edited)
Avatar
tarunon 22-Mar-18 09:41 AM
おお
09:42
あそっか
09:42
funcのoverrideが通常のサブタイピングと同一でないの
Avatar
norio_nomura 22-Mar-18 09:42 AM
Stringはジェネリックになってない。
extension String { … public func hasPrefix(_ prefix: String) -> Bool {
Avatar
tarunon 22-Mar-18 09:42 AM
ここかもしれない、そしてGenericsのサブタイピングに関しての制御を見た記憶がないぞ…
Avatar
omochimetaru 22-Mar-18 09:43 AM
オーバーライドのGeneric制約、バーリトゥード説
Avatar
tarunon 22-Mar-18 09:44 AM
てかそれをするためにはGenericsに関してinとoutがないとだめですよね
09:44
いやでもoveloadを丸めるのは正しく動いてる?これは
Avatar
omochimetaru 22-Mar-18 09:45 AM
こっち向きは正しいよ String is StringProtocol だから、継承先で広く受けるのはOK
Avatar
tarunon 22-Mar-18 09:45 AM
正しくて、ちゃんと動いてる
09:45
僕がTCで読んだのはちょうどclassのoverrideのところで
09:46
protocolのimplとclassのoverrideは別、前者は正しいっぽいが後者は…
Avatar
omochimetaru 22-Mar-18 09:48 AM
protocol ValuePrinter { func print(_ x: Int) func print(_ x: String) } protocol IntOrString { func asInt() -> Int? func asString() -> String? } extension Int : IntOrString { func asInt() -> Int? { return self } func asString() -> String? { return nil } } extension String : IntOrString { func asInt() -> Int? { return nil } func asString() -> String? { return self } } class OmniValuePrinter : ValuePrinter { // oneshot double override! func print<X: IntOrString>(_ x: X) { if let i = x.asInt() { Swift.print(i) } if let s = x.asString() { Swift.print(s) } } } let printer = OmniValuePrinter() as ValuePrinter printer.print(3) printer.print("a")
09:49
おもしろいねえ・・・ TypeScript式オーバーロードを後付できる・・・ (edited)
Avatar
norio_nomura 22-Mar-18 09:54 AM
ジェネリックで範囲を広げてプロトコル準拠とか出来たのね。
09:57
その辺りの挙動、apple/swift内にテスト入ってないかな?
Avatar
tarunon 22-Mar-18 09:58 AM
protocolの方はわかんないですけど、classの方は入ってないっすね
Avatar
omochimetaru 22-Mar-18 10:01 AM
swift - The Swift Programming Language
10:03
このあたりも近そう
Avatar
tarunon 22-Mar-18 10:04 AM
swift - The Swift Programming Language
Avatar
omochimetaru 22-Mar-18 10:04 AM
decl/** に構文単位でいっぱいあるのか。
Avatar
tarunon 22-Mar-18 10:04 AM
そうそう
10:05
decl/class/override.swiftにGenerics周りは、ない
Avatar
norio_nomura 22-Mar-18 10:07 AM
おお、ありがとうございます。
Avatar
norio_nomura 22-Mar-18 11:31 AM
Encoder, DecoderのContainer系メソッドまとめられた。 https://github.com/norio-nomura/ObjectEncoder/pull/22/files (edited)
Avatar
omochimetaru 22-Mar-18 11:33 AM
なるほど!
Avatar
tarunon 22-Mar-18 11:39 AM
おおー
Avatar
norio_nomura 22-Mar-18 12:05 PM
生成されたバイナリを見ると、ちゃんとprotocolに必要なメソッドが生成されてるぽい。
$ nm /Users/norio/Library/Developer/Xcode/DerivedData/ObjectEncoder-cvflgtjlegddrlbosxxjagoaqewr/Build/Products/Debug/ObjectEncoder.framework/ObjectEncoder|xcrun swift-demangle … 00000000000305e0 t _protocol witness for Swift.SingleValueDecodingContainer.decode(Swift.String.Type) throws -> Swift.String in conformance ObjectEncoder.ObjectDecoder.Decoder : Swift.SingleValueDecodingContainer in ObjectEncoder 000000000002f000 t _protocol witness for Swift.SingleValueDecodingContainer.decode(Swift.Bool.Type) throws -> Swift.Bool in conformance ObjectEncoder.ObjectDecoder.Decoder : Swift.SingleValueDecodingContainer in ObjectEncoder 0000000000030430 t _protocol witness for Swift.SingleValueDecodingContainer.decode(Swift.Double.Type) throws -> Swift.Double in conformance ObjectEncoder.ObjectDecoder.Decoder : Swift.SingleValueDecodingContainer in ObjectEncoder 0000000000030280 t _protocol witness for Swift.SingleValueDecodingContainer.decode(Swift.Float.Type) throws -> Swift.Float in conformance ObjectEncoder.ObjectDecoder.Decoder : Swift.SingleValueDecodingContainer in ObjectEncoder …
Avatar
Kishikawa Katsumi 27-Mar-18 05:15 AM
A.swift
class A: AProtocol { init() {} } fileprivate protocol AProtocol { var value: String { get } } extension AProtocol { var value: String { get { return "" } } }
05:15
B.swft
struct B { fileprivate static var a = A() static var v: String { get { return a.value } } }
05:17
^ というのを適当なiOSプロジェクトに書いたとき、リンクエラー(AProtocolがB.swftからは見えないので、a.valueが見つからない)になるんですけど、コンパイルエラーになるべきだと思うのですが、どうでしょうか?
05:18
Xcode 9.2と、2/16時点の4.1およびdev snapshotで確認しました。 (edited)
Avatar
rintaro 27-Mar-18 05:22 AM
エラーになるべきだと思います。
Avatar
Kishikawa Katsumi 27-Mar-18 05:25 AM
@rintaro コンパイルエラーですか?
Avatar
rintaro 27-Mar-18 05:27 AM
はい、 error: 'value' is inaccessible due to 'fileprivate' protection level が正解かと。
Avatar
Kishikawa Katsumi 27-Mar-18 05:28 AM
ありがとうございます。バグレポート送ります。
❤ 1
05:30
簡単なプロジェクトだとメインターゲットのビルドでリンクエラーなんですけど、別のプロジェクトだとテストターゲットをビルドしたときだけリンクエラーになったりするんですよね。それはよくわかりませんでした。
Avatar
rintaro 27-Mar-18 05:31 AM
テストターゲットだけリンクエラーになる場合、メインターゲットはそのプロパティ/メソッドが普通に呼べてしまうということですか?
05:32
もしメインターゲットでそのメソッドを不正使用していないのであれば、リンクしようとしないので素通りするのは理解できます。 (edited)
Avatar
Kishikawa Katsumi 27-Mar-18 05:34 AM
発生したのはレビューがメインのプロジェクトなので実際に呼んでるかどうかは改めて確認しますね。
05:36
おかしいと思ったのはUnit TestではAProtocol、A、Bとも直接的にも間接的にも使用してないので、これはそもそももっと以前にエラーになるはず?と思ったのです。
Avatar
rintaro 27-Mar-18 05:37 AM
Avatar
hiragram 27-Mar-18 05:38 AM
Avatar
rintaro 27-Mar-18 05:38 AM
これまさにこの問題だと思うんですけど、Xcode 9 で直っているって書いてる。
Avatar
Kishikawa Katsumi 27-Mar-18 05:38 AM
試します。
05:40
Xcode 9.2で再現しますね。
Avatar
hiragram 27-Mar-18 05:40 AM
1年前か。
05:41
tarunonに聞いたらデバッグビルドのときtestable importのために本来見えないものが見えるようになってるのではみたいなことを言ってたのこの話だったっけ。
Avatar
tarunon 27-Mar-18 05:42 AM
05:42
そんなこと言ったっけ。。。。
Avatar
rintaro 27-Mar-18 05:42 AM
wmo だとリンク前にインライン化されてリンクエラーにならないっていう落ちっぽい。
Avatar
hiragram 27-Mar-18 05:42 AM
それは別の話だったかなー。debugだと通ってreleaseだと通らないみたいなバグっぽいのも前に引いたことある。
05:43
それこそ去年のtryswiftで話したとかだったから記憶あやふやだー
Avatar
rintaro 27-Mar-18 05:44 AM
エラー
$ swiftc A.swift B.swift -emit-library -module-name MyMod
通る
$ swiftc A.swift B.swift -emit-library -module-name MyMod -wmo
(edited)
Avatar
Kishikawa Katsumi 27-Mar-18 05:44 AM
リリースビルドだとどっちもビルドできますね。
05:44
なるほど。
Avatar
hiragram 27-Mar-18 05:44 AM
wmoってなんですか?
Avatar
rintaro 27-Mar-18 05:44 AM
whole module optimization
Avatar
hiragram 27-Mar-18 05:44 AM
whole module optimizieか
05:45
おお
Avatar
Kishikawa Katsumi 27-Mar-18 05:51 AM
テストターゲットを含めたビルド(⌘+Shift+U)だけで起こるプロジェクトもその時はDebugビルドだから、か。
Avatar
rintaro 27-Mar-18 05:51 AM
その可能性が高そうですね。
Avatar
hiragram 27-Mar-18 05:52 AM
ちょっと思い出した。
debugだと通ってreleaseだと通らないみたいなバグっぽいのも前に引いたことある。
これ逆で、何故かreleaseビルドだと通るんだけどdebugビルドだと通らないのなんでやと思ったんだった。で実はreleaseで通るほうが間違ってたっぽいというやつ
05:52
同じ話ですね
Avatar
omochimetaru 29-Mar-18 02:40 AM
こんなの書いた
public func neverHappen(file: StaticString = #file, line: UInt = #line) -> Never { fatalError("never happen", file: file, line: line) } public func neverHappen<T0>(_ arg0: T0, file: StaticString = #file, line: UInt = #line) -> Never { fatalError("never happen: arg0=\(arg0)") }
例えばこうやって使う
Observable.just(()).asDriver(onErrorRecover: { neverHappen($0) })
(edited)
02:40
本当はこう書きたい・・・
asDriver(onErrorRecover: neverHappen)
(edited)
Avatar
tarunon 29-Mar-18 02:40 AM
できるぞい
02:40
高階関数にしてみれ
Avatar
omochimetaru 29-Mar-18 02:41 AM
asDriver(onErrorRecover: neverHappen()) こういう事?
Avatar
tarunon 29-Mar-18 02:41 AM
あーデフォルト引数ほしいのか (edited)
02:41
欲張りや
Avatar
omochimetaru 29-Mar-18 02:42 AM
そうそう。 もともとは asDriver(onErrorRecover: { _ in neverHappen() }) ってかいてたけど
02:42
バグが見つかった時に _ in で捨てているのはもったいないから
02:42
引数を食う版をオーバーロードしておくというアイデア
Avatar
tarunon 29-Mar-18 02:42 AM
でもasD(onER: nH())の方が良くないかな
02:43
クロージャ毎回作るの考えると
Avatar
omochimetaru 29-Mar-18 02:43 AM
() ついてるの何ってなるでしょ
Avatar
tarunon 29-Mar-18 02:43 AM
慣れるやろ
02:43
高階関数は使えて当たり前な世界になる
Avatar
omochimetaru 29-Mar-18 02:44 AM
default引数を埋めて引数が減った状態の関数型としてサブタイピングがあればいいと思う
02:45
func a(x: Int, y: Int = 3) is (Int) -> Void
Avatar
tarunon 29-Mar-18 02:45 AM
今はそれないよねぇ
Avatar
omochimetaru 29-Mar-18 02:45 AM
でも、関数呼び出し規則については、これが成り立っているでしょ?
Avatar
tarunon 29-Mar-18 02:46 AM
protococの実装も、デフォルト引数でoverloadを横着とかできないから
Avatar
omochimetaru 29-Mar-18 02:46 AM
てことは、推論機構としてはもうあって、関数型の式としてそのまま使う場合にも、この変換を拡張する感じで・・・
Avatar
tarunon 29-Mar-18 02:46 AM
型システムに存在してないんじゃないかな
Avatar
rintaro 29-Mar-18 02:48 AM
デフォルト引数は呼び出しサイトで生成しなきゃならないもの(#fileとか)があるので、結局コンパイラがクロージャ的なコードを生成する必要がある。 (edited)
Avatar
omochimetaru 29-Mar-18 02:49 AM
それは、生成してくれて良いと思います。 xOrNone.map(cat.speak) とかやるときも、 cat を束縛するクロージャができてますよね?
Avatar
tarunon 29-Mar-18 02:50 AM
コンテキスト(ライブラリ)分けてデフォルト引数をstatic propertyとprotocol extensionでガチャガチャやると、ライブラリ側に記述されたデフォルト引数はライブラリ側の型で引っ張られるのは前に実験した
Avatar
omochimetaru 29-Mar-18 02:51 AM
デフォルト引数を生成する小さな関数が作られていて、 コールサイトではそれを呼び出す みたいな形じゃなかったっけ
02:51
昔はコーリーサイトにあって、SEで整理されてたような気が
Avatar
rintaro 29-Mar-18 02:51 AM
生成してくれて良いと思います。
その通りですね。
Avatar
tarunon 29-Mar-18 02:51 AM
今って動きが変わったのかな、やったのは1年くらい前かも
Avatar
rintaro 29-Mar-18 02:53 AM
The current ABI for default arguments generate explicit functions for each default argument in a function. As a simple example, when you call something like this: // In the defining module. func foo(a: Int, b: Int = 42, c: Float = 3.14) { .....
👀 1
Avatar
omochimetaru 29-Mar-18 02:54 AM
18dayのラトナスレだ
02:55
// In the defining module. func foo_impl(a: Int, b: Int, c: Float) {...} func foo_b() -> Int { return 42 } func foo_c() -> Float { return 3.14 } // On the caller side. let bval = foo_b() let cval = foo_c() foo_impl(a: 192, b: bval, c: cval)
↑そうそうコレ
Avatar
rintaro 29-Mar-18 02:55 AM
それが現状を説明している pseudo code ですね。
Avatar
omochimetaru 29-Mar-18 02:56 AM
// In the defining module. func foo_impl(a: Int, b bval: Int?, c val: Float?) { let b = bval ?? 42 let c = cval ?? 3.14 ... } // On the caller side. foo_impl(a: 192, b: nil, c: nil)
02:56
こっちのほうがええんちゃう、と・・・
02:57
あとで会話も追ってみよう。
03:02
てかこういう話題ってevolのpitchだと思ったけど、ABI変更はevol通す必要がないからdevelopmentなのかな?
03:02
developmentカテゴリは興味ない話題も多くて興味ある話題を見逃しがちだ
Avatar
omochimetaru 01-Apr-18 02:49 AM
読んできた ラトナvs スラバ、ジョーグロフという感じ
02:54
どちらの意見もたしかにと思えてめちゃ悩む
03:01
現状:デフォルトパラメータが複雑な式だと呼び出し側が肥大化ないしリザイレント化 対してラトナ式:コードサイズ肥大が無くなる、シンボルが減ってリンクタイム減る 反論とか:だいたいは素朴な式で問題にならない、引数のデフォルト化がABI互換性破壊になる
Avatar
koher 05-Apr-18 08:50 AM
↓で "Implemented (Swift 4.2)" とあるんですが、 4.1 で実装されてますよね?? https://github.com/apple/swift-evolution/blob/master/proposals/0143-conditional-conformances.md
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
tarunon 05-Apr-18 08:51 AM
一部の機能がフライングで入っているので、とか?
08:51
Existentialとか一段飛ばしで実装とか出来ないから、未完成では有るように思います
Avatar
koher 05-Apr-18 08:54 AM
たしかに Hashable の conformance とかまだ入ってないですね。 (edited)
Avatar
ikesyo 05-Apr-18 09:32 AM
ランタイムチェックが実装されたのが4.2なので、それをもってimplementedとしたと考えています
09:33
When evaluating whether a given type conforms to a protocol, evaluate the conditional requirements and pass the results to the witness table accessor function. This provides the ability to query co...
Avatar
koher 05-Apr-18 09:34 AM
なるほど!ありがとうございます🙏
Avatar
ikesyo 05-Apr-18 09:35 AM
それとHashableのやつは https://github.com/apple/swift-evolution/pull/808 で後付でSE-0143に含まれたのでもちろん4.1のタイミングではまだで(当初のスコープ外)、でも https://github.com/apple/swift/pull/15382 がマージされたので4.2に間に合ったと思います(masterからswift-4.2-branchへのリブランチはまだある)。 (edited)
Following discussions on this forum thread, amend SE-0143 to explicitly include the adoption of conditional conformances for Hashable by the following types: Optional Array ArraySlice ContiguousAr...
As a followup to SE-0143, this adds conditional conformance to Hashable to the following types in the standard library: Optional Array, ContiguousArray, ArraySlice Dictionary Range, ClosedRange T...
Avatar
koher 11-Apr-18 09:18 AM
これまで要素が DoubleVector3 とか Vector4 を作ってたけど、仕事で Float にも対応したものがほしくなって、 ARKit の vector_float3 互換にもしたかったので、 gyb で色々生成してみた。(ついでにライブラリ名を SwiftyVector にリネーム) https://github.com/koher/SwiftyVector/blob/0.3.0/Sources/SwiftyVector/Concrete.swift.gyb (edited)
SwiftyVector - Vector types for Swift
09:19
SwiftyVector - Vector types for Swift
09:20
コードジェネレーションもしてるけど、できる限りプロトコルで実装の共通化もしてて、なかなかうまくできたと思う。 https://github.com/koher/SwiftyVector/blob/0.3.0/Sources/SwiftyVector/Vector.swift
SwiftyVector - Vector types for Swift
Avatar
tarunon 17-Apr-18 03:13 AM
protocol Foo { associatedtype Bar } protocol FooA: Foo where Bar == String { } struct FooAImpl: FooA { // typealias Bar == String // Not require } protocol FooB: Foo where Bar == [Piyo] { associatedtype Piyo } struct FooBImpl<P>: FooB { typealias Piyo = P typealias Bar = [Piyo] // Require }
これ結構気になってる
03:14
@swift-4.1.3 @swiftbot --version=latest
protocol Foo { associatedtype Bar } protocol FooA: Foo where Bar == String { } struct FooAImpl: FooA { // typealias Bar == String // Not require } protocol FooB: Foo where Bar == [Piyo] { associatedtype Piyo } struct FooBImpl<P>: FooB { typealias Piyo = P // typealias Bar = [Piyo] // Require }
Avatar
swift41 BOT 17-Apr-18 03:14 AM
error output:
<unknown>:0: error: unknown argument: '--version=latest'
Avatar
swiftbot BOT 17-Apr-18 03:14 AM
Swift version 4.2-dev (LLVM d14a2b25f2, Clang c38020c511, Swift 22530b922f)
03:14
/usercode/main.swift:17:8: error: type 'FooBImpl<P>' does not conform to protocol 'Foo' struct FooBImpl<P>: FooB { ^ /usercode/main.swift:2:20: note: protocol requires nested type 'Bar'; do you want to add it? associatedtype Bar ^ /usercode/main.swift:17:8: error: type 'FooBImpl<P>' does not conform to protocol 'FooB' struct FooBImpl<P>: FooB { ^
Avatar
tarunon 17-Apr-18 03:14 AM
ダメか
03:14
そして4.1側がこけちゃったw
Avatar
Kishikawa Katsumi 17-Apr-18 03:15 AM
@swiftbot --version= latest,4.1
protocol Foo { associatedtype Bar } protocol FooA: Foo where Bar == String { } struct FooAImpl: FooA { // typealias Bar == String // Not require } protocol FooB: Foo where Bar == [Piyo] { associatedtype Piyo } struct FooBImpl<P>: FooB { typealias Piyo = P // typealias Bar = [Piyo] // Require }
Avatar
swiftbot BOT 17-Apr-18 03:15 AM
Swift version 4.1 (swift-4.1-RELEASE)
03:15
/usercode/main.swift:17:8: error: type 'FooBImpl<P>' does not conform to protocol 'Foo' struct FooBImpl<P>: FooB { ^ /usercode/main.swift:2:20: note: protocol requires nested type 'Bar'; do you want to add it? associatedtype Bar ^ /usercode/main.swift:17:8: error: type 'FooBImpl<P>' does not conform to protocol 'FooB' struct FooBImpl<P>: FooB { ^
Avatar
Kishikawa Katsumi 17-Apr-18 03:15 AM
@swiftbot --version=latest,4.1
protocol Foo { associatedtype Bar } protocol FooA: Foo where Bar == String { } struct FooAImpl: FooA { // typealias Bar == String // Not require } protocol FooB: Foo where Bar == [Piyo] { associatedtype Piyo } struct FooBImpl<P>: FooB { typealias Piyo = P // typealias Bar = [Piyo] // Require }
Avatar
swiftbot BOT 17-Apr-18 03:15 AM
Swift version 4.2-dev (LLVM d14a2b25f2, Clang c38020c511, Swift 22530b922f)
👏 1
03:15
/usercode/main.swift:17:8: error: type 'FooBImpl<P>' does not conform to protocol 'Foo' struct FooBImpl<P>: FooB { ^ /usercode/main.swift:2:20: note: protocol requires nested type 'Bar'; do you want to add it? associatedtype Bar ^ /usercode/main.swift:17:8: error: type 'FooBImpl<P>' does not conform to protocol 'FooB' struct FooBImpl<P>: FooB { ^
03:15
Swift version 4.1 (swift-4.1-RELEASE)
03:15
/usercode/main.swift:17:8: error: type 'FooBImpl<P>' does not conform to protocol 'Foo' struct FooBImpl<P>: FooB { ^ /usercode/main.swift:2:20: note: protocol requires nested type 'Bar'; do you want to add it? associatedtype Bar ^ /usercode/main.swift:17:8: error: type 'FooBImpl<P>' does not conform to protocol 'FooB' struct FooBImpl<P>: FooB { ^
Avatar
omochimetaru 17-Apr-18 03:16 AM
structのパラメータPの制約が間接的にFooBのwhereとして書かれてるの?
Avatar
tarunon 17-Apr-18 03:16 AM
つまりFooBはBarが[Piyo]であってほしくて、Piyoはなんでもいい、みたいな
03:16
兎に角Arrayであれば良いみたいなケース
Avatar
omochimetaru 17-Apr-18 03:24 AM
一見FooAとFooBでルールが違うようにみえるけど、typealias経由の解決はしないってことかね
Avatar
tarunon 17-Apr-18 03:24 AM
typealiasの省略の可否が違うのが気になり
Avatar
omochimetaru 17-Apr-18 03:24 AM
typealias Bar = [Piyo] が省略できないのは、 typealias Piyo = P が無いと推論できない事だから?
03:25
一方、typealias Bar == String が省略できるのは、 : FooA だけで推論できることだから?
Avatar
tarunon 17-Apr-18 03:25 AM
Piyo=Pは明示する必要がある、それはわかる。Barが省略できないのは 🤔
Avatar
omochimetaru 17-Apr-18 03:26 AM
論理的には解決可能だよね 単に実装上そうなっちゃってそう
Avatar
tarunon 17-Apr-18 03:27 AM
でもCollection実装するときとかはSubSequenceとか諸々省略可能だよね、どうなってんだろ
Avatar
omochimetaru 17-Apr-18 03:28 AM
フーム・・・
01:00
Swift for TF、普通のDoubleで書かれた関数が、gradient(of: f) で自動微分できてるし python interopがもう動いてた
Avatar
t.ae 24-Apr-18 01:02 AM
Doubleの演算子等が全部自動微分対応のものに差し替わっている?
Avatar
omochimetaru 24-Apr-18 01:02 AM
if文付きの再帰関数も微分できてるし
Avatar
t.ae 24-Apr-18 01:02 AM
というかtfのVariable相当に変わってるのかな
Avatar
omochimetaru 24-Apr-18 01:03 AM
コンパイラが謎拡張されてる
01:03
どうやってるのかとかホワイトペーパーは来月ぐらいに出すって動画中で言ってた
Avatar
t.ae 24-Apr-18 01:03 AM
再帰関数微分とかはdefine by runだとふつうの再帰関数で書いたのでも大丈夫ですね
01:04
動画見てないですけど最初の方でeager modeが云々みたいなのがあったのでそれっぽい
Avatar
omochimetaru 24-Apr-18 01:04 AM
最初の方で言ってるのは
01:04
コンピューティングには2つのやり方があるけど
01:05
コンパイラサポートがあればひとまとめに書けるよね、でもパイソンでは無理だね、みたいなこと話してる
Avatar
t.ae 24-Apr-18 01:05 AM
じゃあdefine and runもできるんですかね
Avatar
omochimetaru 24-Apr-18 01:08 AM
というか、普通の関数が微分できてる時点でそういうことにならない?
01:09
関数の返り値として式ツリーのオブジェクトが返されてるならユーザー実装可能だけど
01:09
シグネチャがそうではないので
01:10
eagerに書いた式がコンパイル時においては式グラフ扱いだからどちらでもあるような。
Avatar
t.ae 24-Apr-18 01:12 AM
if分岐があるのはdefine by runじゃないとできないかと思います。 入力によって計算グラフが変わるので
Avatar
omochimetaru 24-Apr-18 01:12 AM
ifごと微分してるんじゃないの?
01:13
つまり微分された関数にも分岐が残っている
01:13
そうじゃないと区間で定義された関数の微分にならないし。
Avatar
t.ae 24-Apr-18 01:14 AM
define and runだと使われない分岐経路も計算グラフになる define by runだと使われない経路は除外されるって感じですかね
Avatar
omochimetaru 24-Apr-18 01:17 AM
動画の12:31
Avatar
t.ae 24-Apr-18 01:26 AM
dRecurseに3を与えた時点で計算グラフが構築されているとしか考えられない(define by run脳)
Avatar
omochimetaru 24-Apr-18 01:28 AM
まあたしかにこの例だとそう解釈することもできるけど・・・
01:28
そもそもTensorFlowっていうのは
01:28
ユーザ定義型を使って、演算子をオーバーロードすることで、一見通常の計算式を、計算グラフとしてオブジェクト化して
01:28
微分っていう高階操作を行うわけだけど
01:29
あれってその前段の定義ステージと、
01:29
値を流し込む計算ステージの
01:29
2つがあるでしょ
01:29
Pythonだからそれが両方ランタイムで行われているけど
01:29
そもそもコンパイル言語でコードをコンパイルする時はASTを構築しているのだから
01:30
コンパイル時とランタイムに、 ちょうどその定義ステージと計算ステージを割り当てられる
01:30
ってことだと思う
😀 1
Avatar
t.ae 24-Apr-18 01:30 AM
コンパイル時に計算グラフはできてるってことですかね? define and runのフレームワークで再帰関数書いたこと無いのでどうなるのか想像がつかない……
Avatar
omochimetaru 24-Apr-18 01:31 AM
そう
01:32
再帰呼び出しがどう合成されてるかによるけど
01:34
あーどうなんだろ?
Avatar
koher 24-Apr-18 03:13 AM
python interopがもう動いてた
まだ 5:08 までしか見れてないけど、これ Python 関係あるの?直接 Swift から TensorFlow 使う話じゃないの?
03:14
最初字幕なしで見てたら全然聞き取れなかったけど英語字幕あって助かった。
Avatar
omochimetaru 24-Apr-18 03:14 AM
8:54あたりで
03:14
pickleとか使ってますよ。
03:15
SwiftEvolにラトナが提案してる最終型みたいなものがもう動いてる。 (edited)
Avatar
koher 24-Apr-18 03:16 AM
Python 3 と連携できるのかが気になる。
03:18
Python.framework 使ってたら Python 2 しか使えないよね?
Avatar
omochimetaru 24-Apr-18 03:19 AM
直接 Swift から TensorFlow 使う話じゃないの?
import TensorFlow して Tensor<T> とかやってるので、その話もある。
03:20
Python2/3についてはわからない。聴き逃した可能性はあるけど。
03:21
Python.frameworkを使ってたらpython2しか使えないのかはそれもまたわからない。 Py2/3のC-APIの互換性がよくわからないので。 もしかしたらPythonでContext作る時に3モードで構築〜とかできるのかも。
Avatar
koher 24-Apr-18 03:23 AM
SE-0195 で出てくる Python は Python.framework を使ってんじゃないっけ?それだと 2 系になると思うんよね。 https://github.com/apple/swift-evolution/blob/master/proposals/0195-dynamic-member-lookup.md
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
omochimetaru 24-Apr-18 03:24 AM
Python.framworkを使うと2系になるっていう理由はなんですか?
03:24
そこでexportされてるC-APIの詳細仕様をしらないので、そこがよくわからない。
03:24
2-3どっちも使えるC-APIだったら良いなと思って。
Avatar
koher 24-Apr-18 03:26 AM
Python.framework って Mac に標準で入ってるやつで、それが 2 系しかサポートしてないんじゃないかな?詳しくは知らないけど。
03:26
a = someValue[dynamicMember: "someMember"] someValue[dynamicMember: "someMember"] = a mutateParameter(&someValue[dynamicMember: "someMember"])
みたいなのは現状でもやろうと思えばできて、
03:27
SE-0195 は↑を
a = someValue.someMember someValue.someMember = a mutateParameter(&someValue.someMember)
のように書けるようにするだけだと思う。
03:28
Chris Lattner がお試しで作ってた Playground は Python.framework を使ってたような気がする。実際動かしたわけじゃないので確証はないけど。
Avatar
tarunon 24-Apr-18 03:28 AM
import Pythonってやってたからそうじゃないですかね
Avatar
koher 24-Apr-18 03:30 AM
そうすると Python 2 系になっちゃって、 Python 3 系が使えないと interop ができるようになっても辛いなぁと。 3 系の Python.framework も作れるのかもしれないですけど。
Avatar
omochimetaru 24-Apr-18 03:31 AM
Avatar
Kishikawa Katsumi 24-Apr-18 03:31 AM
macOSに標準で付属しているPythonが2.xというだけなので、3.xのPython.frameworkも公式サイトとかからインストールできますよ。
😀 1
Avatar
omochimetaru 24-Apr-18 03:31 AM
インストールを行うといくつかのものが手に入ります
03:31
Python 実行ファイルやライブラリを含む /Library/Frameworks/Python.framework フレームワーク
Avatar
Kishikawa Katsumi 24-Apr-18 03:32 AM
ビルドすることも可能なはず。HomeBrewとかサポートしてるので。
Avatar
omochimetaru 24-Apr-18 03:32 AM
アップルが出荷してるやつが2.7ビルドというだけで
03:32
Python.framework自体は3のもあるみたい
Avatar
koher 24-Apr-18 03:33 AM
3.xのPython.frameworkも公式サイトとかからインストールできますよ。
おお、そうなんですね。それだと大丈夫ですね。
03:33
Python 3 は pyenv でしか使ってませんでした。
Avatar
omochimetaru 24-Apr-18 03:37 AM
クロスのブリッジではなくて、Pythonのビルド一つに一つのフレームワークみたいですね。 includeとかlibみたいなものか。
Avatar
koher 24-Apr-18 03:39 AM
全部 2.7 へのシンボリックリンクになってるけど、仕組み上は一つの framework で色んなバージョンが扱えるわけではない?
$ ls Python.framework/Versions/ 2.3 2.5 2.6 2.7 Current
(edited)
Avatar
omochimetaru 24-Apr-18 03:49 AM
ここまでの情報から考えるとそう思います
03:49
なので3.6のが使いたいなら、それに対応したframeworkがimportされるように、 Swift処理系のframework search pathなどをコントロールする必要がある。
Avatar
Kishikawa Katsumi 24-Apr-18 04:00 AM
Frameworkの仕組み上は複数のバージョンを入れることができて、デフォルトは最新バージョンにリンクするようになっていて、必要に応じて同梱されている別のバージョン(通常は古いバージョン)リンクできる、その場合はバージョンまで含めてSearch Pathに追加する、、、という仕組みのはず。lib〜.soが無印はlatestへのリンクで必要に応じてバージョン付きの.soをリンクするのと同じ、、、はず。
04:02
それはそれとして、Python2と3のような明らかに非互換の変更があるものは別のフレームワークにするべき、なんじゃないですかね。
04:02
2.3-2.7が全部2.7扱いなのはよくわからない。
Avatar
omochimetaru 24-Apr-18 04:02 AM
でもPython界では2と3の両方で使えるコードを書く技法などが普及してますよ
Avatar
Kishikawa Katsumi 24-Apr-18 04:02 AM
たぶん/System/Frameworks以下のPythonは基本的にApple自身が使うことしか考えられてないのかな。 (edited)
Avatar
omochimetaru 24-Apr-18 04:02 AM
それを支援するためのライブラリとかもあるし。
04:03
C-APIレベルでみれば、構文的な差はもうちょっと減るので
04:03
悩ましいラインだと思います
Avatar
koher 24-Apr-18 04:04 AM
でもPython界では2と3の両方で使えるコードを書く技法などが普及してますよ
これには頼らない方がよさそうな気が。
04:05
/System/Library/Frameworks/Python.framework は触らずに別 Framework にした方が良さそうに思います。
Avatar
Kishikawa Katsumi 24-Apr-18 04:05 AM
おもしろいですね。2と3の違いを吸収するレイヤーが作られてる?んですかね。
Avatar
koher 24-Apr-18 04:06 AM
Python 2 は 2020 年にはサポートが切れますし、共存のためにあれこれ労力をかけるより分けておいた方がトラブルも少なそうに思います。 (edited)
Avatar
omochimetaru 24-Apr-18 04:07 AM
概ねの構文や処理系は互換性があって、 一部の 2 の文法は封印、 3の関数は 2側にライブラリとして追加 みたいな感じで・・・ https://hhsprings.bitbucket.io/docs/translations/python/six-doc-ja/
04:08
(まあ個人的には嫌いなんですけど・・・)
Avatar
Kishikawa Katsumi 24-Apr-18 04:08 AM
フレームワーク(ダイナミックライブラリ?)のバージョニングの思想でいうと、普通に使ってるうちはマイナーチェンジは自動的にLatestが使われるけど、それで困りそうなのは別にしろってことだと思うので、Python3が別フレームワークになるのは自然だと思います。
Avatar
omochimetaru 24-Apr-18 04:08 AM
まあたしかに、そういう意味では間違いなくメジャーアップデートですね。
Avatar
koher 24-Apr-18 04:09 AM
map が Python 2 系では List を返していたのが 3 では iterable なオブジェクトになってるとか、吸収しきれなさそう。
Avatar
Kishikawa Katsumi 24-Apr-18 04:09 AM
概ねの構文や処理系は互換性があって、
私もちょこっとPython書いたことあるけど、確かにあまり2と3の違いわかってないんですよね。
Avatar
koher 24-Apr-18 04:11 AM
gyb は Python 2.7 想定だと思うんですけど、普通に Python 3 でも動いてますね。
Avatar
omochimetaru 24-Apr-18 04:11 AM
"" で作られるオブジェクトの型が違うのが一番大きいですね
04:11
たしか2だと素直なバイトバッファで、3だとEncoding付きのUnicodeStringだった気が。
04:14
↑ここに2.7から3.0の書き換えアドバイス?みたいにまとまってます
Avatar
koher 24-Apr-18 04:16 AM
今やるなら基本的には Python 3 になると思いますが、 Swift コンパイラのビルドが Python 2 じゃないといけなくてハマりました。 pyenv でグローバルに 3.6 を指定していたので・・・。
Avatar
N. 24-Apr-18 04:25 AM
https://www.python.org/downloads/release/python-365/ ここにある macOS 64-bit installer で Python 3をインストールしたら、Python.frameworkは /Library/Frameworks にインストールされました。/System/Library/Frameworks 以下はそのままのようですね。
$ ls /Library/Frameworks/Python.framework/Versions 3.6 $ ls /System/Library/Frameworks/Python.framework/Versions 2.3 2.5 2.6 2.7 Current
The official home of the Python Programming Language
🙂 1
Avatar
norio_nomura 24-Apr-18 04:37 AM
pyenvの場合
$ PYTHON_CONFIGURE_OPTS="--enable-framework" pyenv install 3.6.4 python-build: use openssl from homebrew python-build: use readline from homebrew Downloading Python-3.6.4.tar.xz... -> https://www.python.org/ftp/python/3.6.4/Python-3.6.4.tar.xz Installing Python-3.6.4... python-build: use readline from homebrew Installed Python-3.6.4 to /Users/norio/.pyenv/versions/3.6.4 208.44s user 58.92s system 162% cpu 2:44.55 total $ swift `python-config --ldflags` -I `python-config --prefix` Welcome to Apple Swift version 4.1 (swiftlang-902.0.48 clang-902.0.39.1). Type :help for assistance. 1> import Python 2> func execPy(_ code: String) { 3. Py_Initialize() 4. PyRun_SimpleStringFlags(code, nil) 5. Py_Finalize() 6. } 7> execPy("import sys\nprint(sys.version)") 3.6.4 (default, Apr 24 2018, 13:35:20) [GCC 4.2.1 Compatible Apple LLVM 9.1.0 (clang-902.0.39.1)] 8>
(edited)
👏 1
Avatar
koher 24-Apr-18 04:39 AM
おおお・・・、そんなことができるんですね。
Avatar
koher 25-Apr-18 07:56 AM
ArraySlice で任意の範囲のインデックスを持つインスタンスを生成する方法ってありませんか?たとえば↓みたいな感じで。
// こんなことがしたい let slice: ArraySlice<String> = ["a", "b", "c"].offset(100) print(slice[100]) // "a" print(slice[101]) // "b" print(slice[102]) // "c"
(edited)
08:03
そもそも ArraySlice をそういう目的で使うのが間違いな気がしてきました。負のインデックスもできないみたいだし。
08:03
startIndex の前に insert することもできない。
Avatar
norio_nomura 26-Apr-18 05:40 AM
@swift-4.1.3 @swift-4.2.4
struct A { var strings: AnySequence<String> { return AnySequence { () -> AnyIterator<String> in var buffer = staticStrings ?? [] return AnyIterator { if let first = buffer.popFirst() { return first } return nil } } } } let staticStrings: [String]? = ["1", "2"]
(edited)
Avatar
swift41 BOT 26-Apr-18 05:40 AM
stderr:
main.swift:6:32: error: cannot use mutating member on immutable value: 'buffer' is immutable if let first = buffer.popFirst() { ^~~~~~
(edited)
Avatar
norio_nomura 26-Apr-18 05:41 AM
このbufferはimmutableなの?
Avatar
omochimetaru 26-Apr-18 05:42 AM
コピーされた [String] だから 普通にmutableに見える
Avatar
swift42 BOT 26-Apr-18 05:42 AM
exit status: 1 with stderr:
main.swift:6:39: error: '[String]' requires the types '[String]' and 'ArraySlice<String>' be equivalent to use 'popFirst' if let first = buffer.popFirst() { ^
Avatar
omochimetaru 26-Apr-18 05:43 AM
@swift-4.2.4
struct A { var strings: AnySequence<String> { return AnySequence { () -> AnyIterator<String> in var buf: [String] = ["1", "2"] return AnyIterator { if let first = buf.popFirst() { return first } return nil } } } }
Avatar
swift42 BOT 26-Apr-18 05:43 AM
stderr:
main.swift:6:36: error: '[String]' requires the types '[String]' and 'ArraySlice<String>' be equivalent to use 'popFirst' if let first = buf.popFirst() { ^
Avatar
norio_nomura 26-Apr-18 05:43 AM
なんかよくわからん。
Avatar
t.ae 26-Apr-18 05:43 AM
popLastだと動く?
Avatar
omochimetaru 26-Apr-18 05:44 AM
popFirstがそもそも出ない
05:44
IDEで
Avatar
t.ae 26-Apr-18 05:44 AM
それ
05:44
popFirstって導入されたんでしたっけ?前から無かったと思いますけど
05:45
@swift-4.2.4
var buf: [String] = ["1", "2"] buf.popFirst()
Avatar
swift42 BOT 26-Apr-18 05:45 AM
exit status: 1 with stderr:
main.swift:2:5: error: '[String]' requires the types '[String]' and 'ArraySlice<String>' be equivalent to use 'popFirst' buf.popFirst() ^
Avatar
omochimetaru 26-Apr-18 05:45 AM
Playground execution failed: error: iOSGround.playground:13:1: error: cannot use mutating member on immutable value: 'buf' is immutable buf.popFirst() ^~~
05:46
botとxcodeでエラーも違う
Avatar
t.ae 26-Apr-18 05:46 AM
popFirstだけおかしいみたいですかね
05:46
SDK Xcode 7.1+
けっこう古くからあった?補完出ないから気づかなかったということかな
Avatar
norio_nomura 26-Apr-18 05:47 AM
Avatar
omochimetaru 26-Apr-18 05:47 AM
extension Collection where SubSequence == Self { /// Removes and returns the first element of the collection. /// /// - Returns: The first element of the collection if the collection is /// not empty; otherwise, `nil`. /// /// - Complexity: O(1) @_inlineable public mutating func popFirst() -> Element? { // TODO: swift-3-indexing-model - review the following guard !isEmpty else { return nil } let element = first! self = self[index(after: startIndex)..<endIndex] return element } }
05:47
'[String]' requires the types '[String]' and 'ArraySlice<String>' be equivalent
05:47
このメッセージはこのwhereから来てるものか。
Avatar
norio_nomura 26-Apr-18 05:49 AM
なるほど、これで動く。 @swift-4.2.4
struct A { var strings: AnySequence<String> { return AnySequence { () -> AnyIterator<String> in var buffer = ArraySlice(staticStrings ?? []) return AnyIterator { if let first = buffer.popFirst() { return first } return nil } } } } let staticStrings: [String]? = ["1", "2"]
(edited)
Avatar
swift42 BOT 26-Apr-18 05:49 AM
no output (edited)
Avatar
t.ae 26-Apr-18 05:50 AM
SubSeqeuece制約が必要なのはO(1)にするためで、普通のArrayだと適合しないから補完でないのが正しいのか
Avatar
norio_nomura 26-Apr-18 05:50 AM
エラーメッセージがおかしかったのは4.2で直ってるのね。
Avatar
omochimetaru 26-Apr-18 05:50 AM
@swift-4.2.4
var buf = ArraySlice([1,2,3]) print(buf) buf.popFirst() print(buf)
Avatar
swift42 BOT 26-Apr-18 05:50 AM
[1, 2, 3] [2, 3]
stderr:
main.swift:3:5: warning: result of call to 'popFirst()' is unused buf.popFirst() ^ ~~
Avatar
omochimetaru 26-Apr-18 05:50 AM
ああ、それでpopLastと違うのか。
05:50
ArraySliceはオフセットを持ってるからO(1)と
Avatar
t.ae 26-Apr-18 05:51 AM
これO(1)じゃないののオーバーロードじゃだめなんですかね
Avatar
omochimetaru 26-Apr-18 05:52 AM
Let’s Retire Sequence TL;DR Evaluated against its documented purpose, Sequence is not pulling its weight. It creates pitfalls for library users and complexity for everyone. That said, defining a Sequence is super easy. We should make it th...
05:52
まだ読んでないんだけど↑こんな提案出てた
05:52
@koher が前にSequenceに結構突っ込んでたから関係あるかも
Avatar
koher 26-Apr-18 06:01 AM
4.1 でエラーメッセージがバグってるだけそう。
06:01
@swift-4.1.3
var a = [2, 3, 5] print(a.popFirst()!)
(edited)
Avatar
swift41 BOT 26-Apr-18 06:01 AM
exit status: 1 with stderr:
main.swift:2:7: error: cannot use mutating member on immutable value: 'a' is immutable print(a.popFirst()!) ^
(edited)
Avatar
koher 26-Apr-18 06:02 AM
ArraySlice ならちゃんと popFirst があるから使える。 @swift-4.1.3
var a: ArraySlice<Int> = [2, 3, 5] print(a.popFirst()!)
(edited)
Avatar
swift41 BOT 26-Apr-18 06:02 AM
2
(edited)
Avatar
koher 26-Apr-18 06:03 AM
何が起こったんだ??
Avatar
omochimetaru 26-Apr-18 06:04 AM
メンションが。
Avatar
koher 26-Apr-18 06:04 AM
できた。
06:05
一体どうなったらメソッドがないときに error: cannot use mutating member on immutable value: 'a' is immutable なるメッセージが出ることになるのかは興味深いけど・・・。
Avatar
omochimetaru 26-Apr-18 06:05 AM
メソッドは見つかっていて、whereでこけてるけど
06:06
エラーメッセージを出す時に、whereでこけるまでに、mutatabilityのチェックを先にやって
06:06
そっちを吐いちゃってるとか。
06:06
あ、でもmutabilityは通ってるのか。
Avatar
koher 26-Apr-18 06:06 AM
これに関連して、昨日↑に書いたのにも関連してるけど、 Swift では Queue/Deque 的なものは ArraySlice でやるべきと思ってたんだけど、 (edited)
06:07
Swift の ArraySlice はインデックスを保存するから
Avatar
koher 26-Apr-18 06:14 AM
@swiftbot
extension Collection { func indexed() -> [(Index, Element)] { return indices.map { ($0, self[$0]) } } } let a = [ 2, 3, 5, 7, 11, 13] var b = a[2...4] print(Array(b.indexed())) _ = b.popLast() b.append(11) print(Array(b.indexed())) _ = b.popFirst() b.insert(5, at: 3) print(Array(b.indexed()))
🛠 1
Avatar
swiftbot BOT 26-Apr-18 06:14 AM
Swift version 4.1 (swift-4.1-RELEASE)
Avatar
Kishikawa Katsumi 26-Apr-18 06:14 AM
ちょっと空間効率が悪いのを許容してQueueのデータ構造でもインデックスアクセスができるようにしたらいいと思うんですよね。
Avatar
swiftbot BOT 26-Apr-18 06:14 AM
[(2, 5), (3, 7), (4, 11)] [(2, 5), (3, 7), (4, 11)] [(3, 5), (4, 7), (5, 11)]
Avatar
koher 26-Apr-18 06:15 AM
↑の最後で [(2, 5), (3, 7), (4, 11)] を取り戻す方法がない気がしてます。
06:16
インデックスも要素も整数でわかりづらいな・・・。
Avatar
omochimetaru 26-Apr-18 06:16 AM
@koher 生のインデックスじゃなくて
06:16
startIndex + offset
Avatar
koher 26-Apr-18 06:16 AM
@swiftbot
extension Collection { func indexed() -> [(Index, Element)] { return indices.map { ($0, self[$0]) } } } let a = ["a", "b", "c", "d", "e", "f", "g"] var b = a[2...4] print(Array(b.indexed())) _ = b.popLast() b.append("e") print(Array(b.indexed())) _ = b.popFirst() b.insert("c", at: 3) print(Array(b.indexed()))
(edited)
🛠 1
Avatar
swiftbot BOT 26-Apr-18 06:16 AM
Swift version 4.1 (swift-4.1-RELEASE)
(edited)
Avatar
omochimetaru 26-Apr-18 06:17 AM
の形で考えるんじゃないです?
Avatar
swiftbot BOT 26-Apr-18 06:17 AM
[(2, "c"), (3, "d"), (4, "e")] [(2, "c"), (3, "d"), (4, "e")] [(3, "c"), (4, "d"), (5, "e")]
Avatar
koher 26-Apr-18 06:18 AM
@omochimetaru その startIndex を変える方法がない気がしてる。
06:18
endIndex は伸びるんだけど。
06:20
というか、 startIndex の前に挿入できないと全部ずらすことになっていて O(N) になってるかも。
06:21
appendFirst とか pushFirst とか insertFirst がない。
Avatar
omochimetaru 26-Apr-18 06:21 AM
@swiftbot
func indexed<T>(_ slice: ArraySlice<T>) -> [(Int, T)] { return (0..<slice.count).map { (offset: Int) in (offset, slice[slice.startIndex + offset]) } } let a = ["a", "b", "c", "d", "e", "f", "g"] var b = a[2...4] print(indexed(b)) _ = b.popLast() b.append("h") print(indexed(b)) _ = b.popFirst() b.insert("i", at: 3) print(indexed(b))
🛠 1
Avatar
swiftbot BOT 26-Apr-18 06:21 AM
Swift version 4.1 (swift-4.1-RELEASE)
06:21
[(0, "c"), (1, "d"), (2, "e")] [(0, "c"), (1, "d"), (2, "h")] [(0, "i"), (1, "d"), (2, "h")]
Avatar
koher 26-Apr-18 06:22 AM
@omochimetaru それは表示を変えただけでは?
Avatar
omochimetaru 26-Apr-18 06:22 AM
例えばStringをイテレートする時は
06:22
startIndexから初めて、index(after: index)で
06:22
進めていくように
06:23
元々の整数インデックスは気にしないのが正しいArraySliceの触り方なのかな?と
06:23
startIndex の前に挿入できないと全部ずらすことになっていて O(N) になってるかも
それはそんな気がする。
Avatar
koher 26-Apr-18 06:23 AM
ArraySlicesubscript の仕様を使うとおもしろいことができて、
Avatar
omochimetaru 26-Apr-18 06:23 AM
ArraySliceはQueueとは違いそう
Avatar
koher 26-Apr-18 06:24 AM
昨日やってたのは動画のフレームをコマ送りにするときに
06:24
N フレーム分戻れるように画像をキャッシュしてたんだけど
06:25
var cachedFrames = ArraySlice<Image<RGBA<UInt8>>> としてキャッシュしておけば、 (edited)
06:25
cachedFrames[frameIndex] で簡単にアクセスできる。
06:26
if cachedFrames.count > maxNumberOfCachedFrames { cachedFrames.removeFirst() } みたいにして簡単に古いキャッシュを消せるし
06:28
if cachedFrames.indices.contains(frameIndex) { ... } みたいにキャッシュが存在するときの処理も簡単に書ける。
06:29
(↑が O(1) になってるか自信ないけど、 (cachedFrames.startIndex ..< cachedFrames.endIndex).contains(frameIndex) にすれば O(1) ) (edited)
Avatar
omochimetaru 26-Apr-18 06:30 AM
あれ、それって、本当に消えてるんですか?
06:31
ArraySliceのremoveFirstは元々のArrayを保持+オフセットをずらすだけで
06:31
消えないとかないっけ
Avatar
koher 26-Apr-18 06:31 AM
いや、変更を加えた時点で Array とは別物になるし
06:31
そもそも最初から ArraySlice として作ってる。
06:33
@swiftbot
class A { deinit { print("deinit") } } var x: ArraySlice<A> = [A(), A(), A()] print("A") x.removeFirst() print("B") x.removeFirst() print("C") x.removeFirst() print("D")
(edited)
🛠 1
Avatar
swiftbot BOT 26-Apr-18 06:33 AM
Swift version 4.1 (swift-4.1-RELEASE)
(edited)
06:33
A B C D
Avatar
koher 26-Apr-18 06:33 AM
おや
06:35
@swiftbot
class A { deinit { print("deinit") } } var x: ArraySlice<A> = [A(), A(), A()] print("A") x.removeFirst() x[2] = A() print("B") x.removeFirst() x[2] = A() print("C") x.removeFirst() print("D")
🛠 1
Avatar
swiftbot BOT 26-Apr-18 06:35 AM
Swift version 4.1 (swift-4.1-RELEASE)
06:35
A deinit B deinit C D
Avatar
koher 26-Apr-18 06:36 AM
ああ、 CoW でコピー発生してなかった
06:38
コピーが発生したら removeFirst されたやつらも解放されると思うんだけど、どうやって試すのがいいかな・・・。
06:42
@swiftbot
class A { deinit { print("deinit") } } var x = [A(), A(), A()] print("A") x.removeLast() print("B") x.removeLast() print("C") x.removeLast() print("D")
🛠 1
Avatar
swiftbot BOT 26-Apr-18 06:42 AM
Swift version 4.1 (swift-4.1-RELEASE)
06:42
A deinit B deinit C deinit D
Avatar
koher 26-Apr-18 06:42 AM
むー、少なくとも単純に removeFirst じゃ ArraySlice はバッファの中身をクリアしないっぽいな。
Avatar
norio_nomura 26-Apr-18 06:47 AM
CoWの時にもremoveFirstされた要素もコピーされてそう。
Avatar
koher 26-Apr-18 06:48 AM
えー、さすがにそのときは startIndex から endIndex の分だけコピーされてんじゃないかと思ってるんですが。
06:50
ダメっぽい? @swiftbot
class A { deinit { print("deinit") } } var x: ArraySlice<A> = [A(), A(), A()] do { let y = x print("A") x.removeFirst() x[2] = A() print("B") x.removeFirst() x[2] = A() print("C") x.removeFirst() print("D") } print("E")
🛠 1
Avatar
swiftbot BOT 26-Apr-18 06:50 AM
Swift version 4.1 (swift-4.1-RELEASE)
06:50
A B deinit C D deinit deinit E
06:50
/usercode/main.swift:7:9: warning: initialization of immutable value 'y' was never used; consider replacing with assignment to '_' or removing it let y = x ~~~~^ _
Avatar
rintaro 26-Apr-18 07:01 AM
@swiftbot
class A : CustomStringConvertible{ let val: Int init(_ val: Int) { self.val = val } deinit { print("deinit: \(self)") } var description: String { return "A(\(val))" } } var x: ArraySlice<A> = [A(1), A(2), A(3)] do { let y = x print("A") x.removeFirst() x[2] = A(4) print("B") x.removeFirst() x[2] = A(5) print("C") x.removeFirst() print("D") } print("E")
🛠 1
Avatar
swiftbot BOT 26-Apr-18 07:02 AM
Swift version 4.1 (swift-4.1-RELEASE)
07:02
A B deinit: A(4) C D deinit: A(1) deinit: A(3) E
07:02
/usercode/main.swift:12:7: warning: initialization of immutable value 'y' was never used; consider replacing with assignment to '_' or removing it let y = x ~~~~^ _
Avatar
rintaro 26-Apr-18 07:02 AM
なぜ A(1) が deinit されるのか?
Avatar
koher 26-Apr-18 07:06 AM
確かに(元のコードでも)そこで 2 回 deinit されてるの変だ。なんで 1 も解放されてるんだろう・・・。 (edited)
Avatar
norio_nomura 26-Apr-18 07:07 AM
その出力を見る限り、removeFirstされた要素はCoWでコピーされてない様ですね。
07:08
x[2] = A(4)
でCoW発生か。
Avatar
koher 26-Apr-18 07:09 AM
でも A(2) も解放されないといけない気が。ちょっと紙に書いてみないと頭の中で CoW 含む参照関係が追えなくなってきたので間違ってるかもですが・・・。
Avatar
rintaro 26-Apr-18 07:11 AM
ですね。もし開放されるなら A(2) もされるべきっぽいし、妙に中途半端。
Avatar
norio_nomura 26-Apr-18 07:11 AM
CoW時の境界チェックがバグってるぽい。バグってないと思う。 (edited)
Avatar
koher 26-Apr-18 08:23 AM
@swiftbot
class A : CustomStringConvertible { let value: Int init(_ value: Int) { self.value = value } var description: String { return "A(\(value))" } deinit { print("deinit \(self)") } } do { var x: ArraySlice<A> = [] for i in 0..<20 { x.append(A(i)) } while let a = x.popFirst() { print("pop \(a)") } print("-----") }
🛠 1
Avatar
swiftbot BOT 26-Apr-18 08:23 AM
Swift version 4.1 (swift-4.1-RELEASE)
08:23
pop A(0) pop A(1) pop A(2) pop A(3) pop A(4) pop A(5) pop A(6) pop A(7) pop A(8) pop A(9) pop A(10) pop A(11) pop A(12) pop A(13) pop A(14) pop A(15) pop A(16) pop A(17) pop A(18) pop A(19) ----- deinit A(0) deinit A(1) deinit A(2) deinit A(3) deinit A(4) deinit A(5) deinit A(6) deinit A(7) deinit A(8) deinit A(9) deinit A(10) deinit A(11) deinit A(12) deinit A(13) deinit A(14) deinit A(15) deinit A(16) deinit A(17) deinit A(18) deinit A(19)
Avatar
koher 26-Apr-18 08:23 AM
@swiftbot
class A : CustomStringConvertible { let value: Int init(_ value: Int) { self.value = value } var description: String { return "A(\(value))" } deinit { print("deinit \(self)") } } var i = 0 do { var x: ArraySlice<A> = [] do { for _ in 0..<20 { x.append(A(i)) i += 1 } while let a = x.popFirst() { print("pop \(a)") if !x.isEmpty { x[x.endIndex - 1] = A(i) i += 1 } } } print("-----") }
🛠 1
Avatar
swiftbot BOT 26-Apr-18 08:23 AM
Swift version 4.1 (swift-4.1-RELEASE)
08:23
pop A(0) deinit A(19) pop A(1) deinit A(20) pop A(2) deinit A(21) pop A(3) deinit A(22) pop A(4) deinit A(23) pop A(5) deinit A(24) pop A(6) deinit A(25) pop A(7) deinit A(26) pop A(8) deinit A(27) pop A(9) deinit A(28) pop A(10) deinit A(29) pop A(11) deinit A(30) pop A(12) deinit A(31) pop A(13) deinit A(32) pop A(14) deinit A(33) pop A(15) deinit A(34) pop A(16) deinit A(35) pop A(17) deinit A(36) pop A(18) deinit A(37) pop A(38) ----- deinit A(0) deinit A(1) deinit A(2) deinit A(3) deinit A(4) deinit A(5) deinit A(6) deinit A(7) deinit A(8) deinit A(9) deinit A(10) deinit A(11) deinit A(12) deinit A(13) deinit A(14) deinit A(15) deinit A(16) deinit A(17) deinit A(18) deinit A(38)
Avatar
koher 26-Apr-18 08:24 AM
これはちゃんと動いてそう。
08:25
while let ちゃんと使ったの初めてかも。
Avatar
norio_nomura 26-Apr-18 08:28 AM
でも A(2) も解放されないといけない気が。
これってCoW時点ではA(2)もコピーされてるから、解放されなくて正解な気が。 @swift-4.1.3
class A : CustomStringConvertible{ let val: Int init(_ val: Int) { self.val = val } deinit { print("deinit: \(self)") } var description: String { return "A(\(val))" } } var x: ArraySlice<A> = [A(1), A(2), A(3)] do { let y = x // yは[A(1), A(2), A(3)]を保持 print("A") x.removeFirst() // xは[A(1), A(2), A(3)]を保持して[A(2), A(3)]を露出 x[2] = A(4) // CoW発生、xは[A(2), A(4)]を保持 print("B") x.removeFirst() // xは[A(2), A(4)]を保持して[A(4)]を露出 x[2] = A(5) // xは[A(2), A(5)]を保持して[A(5)]を露出、A(4)解放 print("C") x.removeFirst() // xは[A(2), A(5)]を保持して[]を露出 print("D") } // y解放、xに保持されていないA(1),A(3)解放 print("E")
(edited)
Avatar
swift41 BOT 26-Apr-18 08:34 AM
A B deinit: A(4) C D deinit: A(1) deinit: A(3) E
stderr:
main.swift:12:7: warning: initialization of immutable value 'y' was never used; consider replacing with assignment to '_' or removing it let y = x ~~~~^ _
Avatar
swift41 BOT 26-Apr-18 08:48 AM
A B deinit: A(4) C D deinit: A(1) deinit: A(3) E
stderr:
main.swift:12:9: warning: initialization of immutable value 'y' was never used; consider replacing with assignment to '_' or removing it let y = x // yは[A(1), A(2), A(3)]を保持
Avatar
rintaro 26-Apr-18 09:38 AM
なるほどー
Avatar
koher 27-Apr-18 09:24 AM
今更ですが確認しました。 x[2] = A(5) でコピーが発生してなかったんですね😅
Avatar
koher 02-May-18 08:08 AM
Dictionary にある Key のエントリーが含まれるかどうかを調べる一番いい方法って dictionary.keys.contains(key) でいいんでしたっけ? O(1) になることのドキュメントが見つけられず・・・。
08:08
dictionary[key] != nil は不細工なので。
Avatar
tarunon 02-May-18 08:10 AM
keys作っちゃうとそこのオーバーヘッドが大変そう
Avatar
Kishikawa Katsumi 02-May-18 08:12 AM
かっこいいかどうかはともかく、 index(forKey:) が目当てのメソッドじゃないしょうか?
Avatar
rintaro 02-May-18 08:21 AM
https://github.com/apple/swift-evolution/blob/master/proposals/0154-dictionary-key-and-value-collections.md#proposed-solution Keys 実装目的の最初に挙げられているくらいなので、O(1) だと思うんですが、実装追えてないです。
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
Avatar
Kishikawa Katsumi 02-May-18 08:22 AM
https://github.com/apple/swift/blob/82226642c2459c0f5d2054fe1f6545b57efafffb/stdlib/public/core/Dictionary.swift#L655-L660 なんかNSDictionaryをラップしてる場合はO(n)と書いてあります。
swift - The Swift Programming Language
08:22
^ はindex(forKey:) についての話です。
08:25
かっこよくないと思いますけど dictionary[key] != nil は一番わかりやすいと思いますね。
Avatar
rintaro 02-May-18 08:25 AM
追いました。 https://github.com/apple/swift/blob/82226642c2459c0f5d2054fe1f6545b57efafffb/stdlib/public/core/Dictionary.swift#L1255-L1258 Dictionary.Keys.contains(_:) は最終これが呼ばれるので、O(1) ですね。(Nativeの場合) (edited)
swift - The Swift Programming Language
🙏 1
Avatar
hironytic 02-May-18 08:26 AM
あれでも、結局、 index(forKey:) と同じってこと?
Avatar
Kishikawa Katsumi 02-May-18 08:27 AM
_variantBuffer.index(forKey:) は結局 Dictionary.index(forKey:) と同じですね。
Avatar
koher 02-May-18 08:27 AM
おおお、そんなところ( Proposal )に書いてあったんですね・・・。
Avatar
hironytic 02-May-18 08:30 AM
keys は struct 1つ作るだけだからそんなにオーバーヘッドなさそう https://github.com/apple/swift/blob/82226642c2459c0f5d2054fe1f6545b57efafffb/stdlib/public/core/Dictionary.swift#L1169-L1173
swift - The Swift Programming Language
Avatar
koher 02-May-18 08:32 AM
index(for:) にしても nil と比較することになると思うんで、ダイレクトにキーが存在するかを調べているということをコード上で表し、かつオーバーヘッドの少ない(最低でも O(1) の)方法はなんだろうということでした。
08:32
安心して dictionary.keys.contains(key) 使うことにします。
🙂 1
Avatar
tarunon 02-May-18 08:35 AM
Keysもcow効くのすごい
Avatar
rintaro 02-May-18 08:37 AM
_customContainsEquatableElement mayBeGet(key) != nil を直接使わず index(forKey: key) != nil なのは何故なんだろう。 (edited)
Avatar
koher 02-May-18 08:41 AM
キーがないということを明確に表したかったとか?でもそのせいで NSDictionary をラップしてたら O(1) じゃなくなってる?? (edited)
Avatar
hironytic 02-May-18 08:49 AM
NSDictionary をラップしてないときは、 _variantBufferNativeDictionaryBuffer で、それだと、 index(forKey:)maybeGet_find を呼ぶことになるので同じですよね。(値を取得しない分、 index(forKey:) の方が得)
08:50
NSDictionary をラップしているときは、 _CocoaDictionaryBuffer なので、 index(forKey:) が中で mayBeGet を呼ぶようになっているので、結局同じっぽいような。
Avatar
rintaro 02-May-18 08:53 AM
ああ、Native の方だと index(forKey:) のほうが特なのですね。納得。 Cocoa のほうだと、maybeGet で見つかったときに、比較的重い処理 https://github.com/apple/swift/blob/82226642c2459c0f5d2054fe1f6545b57efafffb/stdlib/public/core/Dictionary.swift#L3026-L3036 が入るので、何故なんだろうと思ったのです。
swift - The Swift Programming Language
Avatar
hironytic 02-May-18 08:55 AM
あ、ほんとだ。この重い処理は何なんでしょう
08:55
ああ、Indexを探しているのか。
Avatar
koher 02-May-18 09:07 AM
https://github.com/apple/swift/blob/82226642c2459c0f5d2054fe1f6545b57efafffb/stdlib/public/core/Dictionary.swift#L1255-L1258index(for:) を呼ばずに https://github.com/apple/swift/blob/82226642c2459c0f5d2054fe1f6545b57efafffb/stdlib/public/core/Dictionary.swift#L3397-L3420 みたいな分岐をして .cocoa のときに maybeGet なり何なりを使って検査するようにすれば NSDictionary をラップしてても dictionary.keys.contains(key) を O(1) にできるような気がするんですが、そんなことはないですか?
swift - The Swift Programming Language
swift - The Swift Programming Language
Avatar
rintaro 02-May-18 09:09 AM
_VariantDictionaryBuffer にそれ用のメソッドを作って、_customContainsEquatableElement から呼ぶべきだと思いますが、はいキーの有無だけであれば O(1) にできると思います。 (edited)
Avatar
koher 02-May-18 09:12 AM
_VariantDictionaryBuffer 側に containsKey みたいなメソッドを作ってそれを呼ぶのがいいんでしょうか。 (edited)
Avatar
rintaro 02-May-18 09:13 AM
だと思います。
🙂 1
Avatar
koher 02-May-18 09:42 AM
NSDictionary をラップしてても O(1) になってる? @swiftbot
import Foundation let native1M = [String: String](uniqueKeysWithValues: (1...1_000_000).map { ("\($0)", "\($0)") }) let cocoa1M = (native1M as NSDictionary) as! [String: String] let native2M = [String: String](uniqueKeysWithValues: (1...2_000_000).map { ("\($0)", "\($0)") }) let cocoa2M = (native2M as NSDictionary) as! [String: String] let n = 10 func measure(_ operation: () -> ()) { var sum: TimeInterval = 0 for i in 1...n { let start = Date.timeIntervalSinceReferenceDate operation() let end = Date.timeIntervalSinceReferenceDate let interval = end - start print("\(i): \(interval)") sum += interval } print("avg: \(sum / TimeInterval(n))") } let dictionaries: [(String, [String: String])] = [ ("Native 1M", native1M), ("Cocoa 1M", cocoa1M), ("Native 2M", native2M), ("Cocoa 2M", cocoa2M), ] for (name, dictionary) in dictionaries { print(name) measure { for i in 1...100 { _ = dictionary.keys.contains("\(i)") } } }
🛠 1
Avatar
swiftbot BOT 02-May-18 09:42 AM
Swift version 4.1 (swift-4.1-RELEASE)
09:42
/usercode/main.swift:4:16: error: cannot convert value of type '[String : String]' to type 'NSDictionary' in coercion let cocoa1M = (native1M as NSDictionary) as! [String: String] ^~~~~~~~ /usercode/main.swift:6:16: error: cannot convert value of type '[String : String]' to type 'NSDictionary' in coercion let cocoa2M = (native2M as NSDictionary) as! [String: String] ^~~~~~~~
Avatar
koher 02-May-18 09:43 AM
あれ?手元では通ってるのに。
09:43
あ、 Linux だからか。
09:43
そりゃダメだ。
Avatar
rintaro 02-May-18 09:53 AM
as! [String: String] の時点でどうもNativeに変換されているっぽいですね。
Avatar
koher 02-May-18 09:55 AM
なるほど。
09:55
何かの Obj-C の API を介さないといけないということでしょうか
Avatar
rintaro 02-May-18 09:56 AM
import Foundation let native1M = [NSString: NSString](uniqueKeysWithValues: (1...1_000_000).map { ("\($0)" as NSString, "\($0)" as NSString) }) let cocoa1M = NSDictionary(dictionary: native1M) as! [NSString: NSString] let native2M = [NSString: NSString](uniqueKeysWithValues: (1...2_000_000).map { ("\($0)" as NSString, "\($0)" as NSString) }) let cocoa2M = NSDictionary(dictionary: native2M) as! [NSString: NSString] let n = 10 func measure(_ operation: () -> ()) { var sum: TimeInterval = 0 for i in 1...n { let start = Date.timeIntervalSinceReferenceDate operation() let end = Date.timeIntervalSinceReferenceDate let interval = end - start print("\(i): \(interval)") sum += interval } print("avg: \(sum / TimeInterval(n))") } let dictionaries: [(String, [NSString: NSString])] = [ ("Native 1M", native1M), ("Cocoa 1M", cocoa1M), ("Native 2M", native2M), ("Cocoa 2M", cocoa2M), ] for (name, dictionary) in dictionaries { print(name) measure { for i in 1...100 { _ = dictionary.keys.contains("\(i)" as NSString) } } }
これで確認できました。
(edited)
Avatar
koher 02-May-18 10:00 AM
ありがとうございます!
Avatar
koher 02-May-18 01:45 PM
とりあえず Swift コンパイラをビルドして↑が再現することが確認できました。修正してみます。
Avatar
koher 02-May-18 02:03 PM
Before
Native 1M 1: 0.00014901161193847656 2: 9.000301361083984e-05 3: 8.797645568847656e-05 4: 8.702278137207031e-05 5: 8.809566497802734e-05 6: 8.702278137207031e-05 7: 8.797645568847656e-05 8: 8.702278137207031e-05 9: 8.702278137207031e-05 10: 8.809566497802734e-05 avg: 9.392499923706054e-05 Cocoa 1M 1: 1.5260519981384277 2: 1.4988809823989868 3: 1.4609719514846802 4: 1.4877859354019165 5: 1.4853370189666748 6: 1.4784049987792969 7: 1.4788520336151123 8: 1.4836270809173584 9: 1.5162140130996704 10: 1.471932053565979 avg: 1.4888058066368104 Native 2M 1: 9.799003601074219e-05 2: 7.700920104980469e-05 3: 7.605552673339844e-05 4: 7.605552673339844e-05 5: 7.700920104980469e-05 6: 7.700920104980469e-05 7: 7.593631744384766e-05 8: 7.700920104980469e-05 9: 7.700920104980469e-05 10: 9.09566879272461e-05 avg: 8.020401000976562e-05 Cocoa 2M 1: 2.558851957321167 2: 2.5838489532470703 3: 2.5781790018081665 4: 2.586503028869629 5: 2.5640339851379395 6: 2.611467957496643 7: 2.587472081184387 8: 2.5809329748153687 9: 2.5621449947357178 10: 2.583261013031006 avg: 2.5796695947647095
14:04
After
Native 1M 1: 0.0001779794692993164 2: 9.298324584960938e-05 3: 9.000301361083984e-05 4: 8.90493392944336e-05 5: 8.893013000488281e-05 6: 8.90493392944336e-05 7: 0.00011992454528808594 8: 0.0001380443572998047 9: 9.799003601074219e-05 10: 9.59634780883789e-05 avg: 0.00010799169540405273 Cocoa 1M 1: 0.00013005733489990234 2: 9.799003601074219e-05 3: 9.799003601074219e-05 4: 9.799003601074219e-05 5: 9.799003601074219e-05 6: 9.799003601074219e-05 7: 9.799003601074219e-05 8: 9.906291961669922e-05 9: 9.799003601074219e-05 10: 9.799003601074219e-05 avg: 0.0001013040542602539 Native 2M 1: 0.00010597705841064453 2: 9.000301361083984e-05 3: 9.000301361083984e-05 4: 8.893013000488281e-05 5: 8.90493392944336e-05 6: 8.90493392944336e-05 7: 8.893013000488281e-05 8: 9.000301361083984e-05 9: 9.000301361083984e-05 10: 8.90493392944336e-05 avg: 9.109973907470704e-05 Cocoa 2M 1: 0.00010001659393310547 2: 9.799003601074219e-05 3: 9.799003601074219e-05 4: 9.906291961669922e-05 5: 9.799003601074219e-05 6: 9.799003601074219e-05 7: 9.799003601074219e-05 8: 9.799003601074219e-05 9: 9.894371032714844e-05 10: 9.799003601074219e-05 avg: 9.839534759521484e-05
Avatar
koher 02-May-18 02:15 PM
@rintaro PR 送ろうと思うんですが、こういう場合のパフォーマンスのテストの参考になりそうなものありますか?
Avatar
koher 02-May-18 02:28 PM
swift - The Swift Programming Language
Avatar
koher 02-May-18 04:58 PM
Dictionary.Keys.contains(_:) takes O(1) for native dictionaries. However it takes O(n) when dictionaries wrap a NSDictionary. This PR makes it to take just O(1) even when wrapping a NSDictionary. B...
💯 2
Avatar
rintaro 03-May-18 01:16 PM
ああー、反応できなくてごめんなさい。大丈夫だとおもいます!
🙂 1
Avatar
koher 09-May-18 05:17 AM
@Kishikawa Katsumi @hironytic @rintaro この前話してた dictionary.keys.contains(key) ですが、↑の PR がマージされたので NSDictionary をラップしてる場合でも O(1) になりました😀
👏 6
Avatar
Kishikawa Katsumi 09-May-18 05:18 AM
そうすると、ヘッダのドキュメントの記述も直したほうが良さそう?
Avatar
koher 09-May-18 05:25 AM
O(n) って書いてあったのってここ↓じゃありませんっけ? https://github.com/apple/swift/blob/8afa9b1dcd2b535fb2b84ec87cafd36457d8eca6/stdlib/public/core/Dictionary.swift#L658 (edited)
swift - The Swift Programming Language
Avatar
Kishikawa Katsumi 09-May-18 05:28 AM
そうです。そこの // Complexity: amortized O(1) for native buffer, O(n) when wrapping an // NSDictionary. っていうのはもう消していいのかなと。
Avatar
koher 09-May-18 05:30 AM
僕の PR は( NSDictionary をラップしているときに)それを使わないようにして O(n) を回避しているので、 index(for:) はそのままのはずですね。 (edited)
Avatar
Kishikawa Katsumi 09-May-18 05:30 AM
あ、そうなんですね。index(for:) からそれが呼ばれてるのだと思ってました。
Avatar
koher 09-May-18 05:32 AM
_variantBuffer index(for:) を呼ぶ代わりに↓を呼ぶようになっています。
internal func containsKey(_ key: Key) -> Bool { if _fastPath(guaranteedNative) { return asNative.index(forKey: key) != nil } switch self { case .native: return asNative.index(forKey: key) != nil #if _runtime(_ObjC) case .cocoa(let cocoaBuffer): return SelfType.maybeGetFromCocoaBuffer(cocoaBuffer, forKey: key) != nil #endif } }
05:33
Native のときは index(for:) が呼ばれますが、 NSDictionary をラップしているときは maybeGetFromCocoaBuffer になります。 (edited)
05:35
index もいらないんで、その生成をショートカットできるならわずかにオーバーヘッドを減らせるかもしれないです。が、 O(1) が保証されることが一番大事だと思うので。
Avatar
norio_nomura 22-May-18 12:21 AM
@compilerEvaluable いいね。今はllvmが特定のc関数についてやってるだけなのかな? https://forums.swift.org/t/pitch-compile-time-constant-expressions-for-swift/12879
Chris Lattner and I have been working on a proposal to add compile-time constant expressions to Swift. Our goal is to create a very general feature that enables many other useful features that need compile-time execution, like: static assertions, value parameters in generics,...
Avatar
omochimetaru 22-May-18 01:29 AM
貼ろうとしたらもう貼られてた。アツい提案が来ましたね、コンパイル時計算のプロポーザルが Authors: Marc Rasi, Chris Lattner から。
01:35
SILパスとしてinterpreterが追加されてそこでコードを評価するみたい。 取り扱える言語仕様はSwiftのサブセットで、提案の中で詳細に定義されてる(長い)
Avatar
tarunon 22-May-18 01:36 AM
型チェックはあるのかな
Avatar
omochimetaru 22-May-18 01:36 AM
型があるね
Avatar
tarunon 22-May-18 01:37 AM
素晴らしい、Genericsをconditionedにするとexistentialとれないから、「ExistentialをとるGenerics」はAnyだったんだけど、これがあれば保証できるようになる
01:37
実行時fatalじゃなくなるぞ
Avatar
omochimetaru 22-May-18 01:37 AM
This interpreter keeps track of intermediate values using an algebraic data type (ADT) whose variants correspond to the types that the interpreter can operate on. We call these "compiler-representable types".
01:37
compiler representable type に限定されるらしい。どういうのがそれなのかはよくわかんない。
Avatar
tarunon 22-May-18 01:38 AM
むむ
Avatar
omochimetaru 22-May-18 01:38 AM
とりあえず、Standard library Bool and Int types, Struct, Tupleが書いてある。
01:39
Types This model supports: builtin integer type tuples of compiler-representable types user-defined structs whose fields are compiler-representable types, which are defined in the current module or which otherwise have a known/fixed layout. metatypes addresses of stack objects
Avatar
tarunon 22-May-18 01:39 AM
これは雰囲気Protocol使えなさそうやなぁ
Avatar
omochimetaru 22-May-18 01:40 AM
いまのところ無いね。
Avatar
koher 24-May-18 07:59 AM
#swiftbot-sandbox でやった↓だけど、 Randomstruct っぽくない挙動をする・・・。
var a = Random.default var b = a print(a.next()) print(b.next())
2190522142258413190 6214093798825593358
08:03
仕方ない気もするけど。
Avatar
t.ae 24-May-18 08:03 AM
実装みた感じだと自身で種をもってないっぽい?
Avatar
koher 24-May-18 08:08 AM
単に自身で seed を持つようにしただけだと、 Random.default.next() と呼び出さない限り毎回初期化されちゃうから、
Avatar
t.ae 24-May-18 08:08 AM
内部はarc4randomとかそもそも種持てないやつか
Avatar
koher 24-May-18 08:08 AM
Random.default の度に色々やんないといけなくなっちゃう。
Avatar
t.ae 24-May-18 08:08 AM
nextがmutatingなのもミスリーディングですね
Avatar
koher 24-May-18 08:08 AM
まあ、ハードウェアノイズ使おうとすると原理的に無理か。
08:09
struct なのがミスリーディングな気も。 class の方がよい?🤔
Avatar
omochimetaru 24-May-18 08:09 AM
それ議論されてました
08:11
Sure. Small disclaimer that this was originally written back in the Swift 1~2 days, so it is overdue for a simplifying rewrite. Also, I should point out that the term “Source” has a special meaning in my code. It basically means that something will provide an ~infinite ...
08:11
どこだったかな・・・
08:11
structの方が早いって計測結果とか貼られてた
08:12
Generators as reference vs value types I think we should require Generators to be classes. It simplifies calling the functions and I don’t see any clear advantage of using struct Generators.
08:12
ここらへんから。
Avatar
t.ae 24-May-18 08:17 AM
https://forums.swift.org/t/se-0202-random-unification/11313/186 Random自体じゃないですけど変わらないって言ってるような
08:18
Random自体をどっちにするかの話もでてきてます?
Avatar
omochimetaru 24-May-18 08:19 AM
Random自体とは?
Avatar
t.ae 24-May-18 08:19 AM
この比較は自作のXoroshiroとかでstruct/classの比較をしてますけど組み込みのRandomの速度については書いて無さそう
Avatar
omochimetaru 24-May-18 08:19 AM
Look! The results for the struct and class versions of your Xorshift128Plus and LinearCongruential are now the same!
早さは一緒って言ってたか。
08:20
組み込みのRandomが結局なんなのかよくわかっていない。
08:20
この先の会話を読むとわかりそう?
Avatar
t.ae 24-May-18 08:21 AM
swift - The Swift Programming Language
08:26
英語が難しい
Avatar
koher 29-May-18 07:15 AM
↓これってどうやればいいんですっけ?
func foo<S : Sequence>(_ sequence: S) { ... } let a: Any = ... // a が Sequence か調べて Sequence のときは foo に渡すにはどうすればいい?
Avatar
t.ae 29-May-18 07:26 AM
AnySequence使っては?
Avatar
omochimetaru 29-May-18 07:26 AM
できない気がする。
Avatar
t.ae 29-May-18 07:27 AM
確かにコンストラクタに渡せないか
Avatar
omochimetaru 29-May-18 07:27 AM
既知の様々なSequenceを総当たりしないと。
Avatar
koher 29-May-18 07:39 AM
これできないの辛くないかな? Any に限らず Foo の中から BarProtocol を満たすものだけを渡したいってのができない。
07:40
処理系的にはできそうな気がするけど構文が存在しない?
Avatar
omochimetaru 29-May-18 07:40 AM
処理系的に無理じゃないですか?
07:41
あー一応ジェネリクスのコンパイル先のSequenceのExistential表現は存在するか
07:41
今は無いけど原理的にはできるって感じがする。
Avatar
koher 29-May-18 07:41 AM
うん、スペシャライズされないときに処理してるはずだから
Avatar
omochimetaru 29-May-18 07:41 AM
まあ結局Existentialがほしいってことですよね
Avatar
koher 29-May-18 07:41 AM
うーん、 existential そのものじゃなくていいんよね。
07:42
as して渡すだけだから、型として表に見えなくていい。
Avatar
omochimetaru 29-May-18 07:42 AM
ジェネリックな関数に渡せるだけで
07:42
変数の型としては使えなくてもいいってことですか?
Avatar
koher 29-May-18 07:42 AM
はい
Avatar
omochimetaru 29-May-18 07:43 AM
if let seq = a as Sequence { // でもこれができちゃうよ print(type(of: seq)) foo(seq) }
(edited)
Avatar
koher 29-May-18 07:43 AM
first class の existential じゃなくて、 <S : Sequence> に渡せるようにするだけの限定的なやつ
07:44
そのコードだといかにも existential っぽいから
07:44
新しい構文が必要そう。
Avatar
koher 29-May-18 07:53 AM
うーん、いい構文が思いつかない。 generalized existential が一番シンプルなのかな・・・
Avatar
omochimetaru 29-May-18 08:10 AM
generalized existentialなんですけど Any<Sequence where .Iterator.Element == String> この表記、 型パラメータを一つ取るジェネリック型Anyがあるように見えてしまう気がしてきた
Avatar
koher 29-May-18 08:19 AM
@omochimetaru 元々は普通のプロトコルの existential も Any<FooProtocol> にしようという話があって、その時代に書かれたものだから。
08:22
ちがった。 protocol<A, B>Any<A, B> にしようってだけだったか。 https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md#renaming-protocol-to-any-
swift - The Swift Programming Language
08:23
いずれにせよ Any<A, B>A & B になった以上、 generilized existential の構文も変更しないといけない気がする。それ以前に、あまり導入する気もなさそうな・・・。
Avatar
omochimetaru 29-May-18 08:23 AM
Any<A, B> になりかけて A & B になったから僕の言ったような問題は今は無いのか
08:24
その延長でいくと普通に let a: Sequence where Element == Int & Foo みたいになりそうだ。
Avatar
koher 01-Jun-18 10:17 AM
プロパティに対して↓のようなことができる方法ってないですか?
struct Foo { // method func a() -> Int { return 2 } // computed property var b: Int { return 3 } // stored property let c: Int = 5 } let foo = Foo() print(Foo.a(foo)()) // OK print(Foo.b(foo)) // NG print(Foo.c(foo)) // NG
Avatar
tarunon 01-Jun-18 10:19 AM
自分で書くしかないような
Avatar
omochimetaru 01-Jun-18 10:19 AM
KeyPath
print(foo[keyPath: \Foo.b])
Avatar
tarunon 01-Jun-18 10:22 AM
KeyPath、structでも動くの知らなかった
Avatar
omochimetaru 01-Jun-18 10:23 AM
処理系としてはMetaClassの中にレイアウト情報があってそれで動いてるはず
Avatar
tarunon 01-Jun-18 11:10 AM
@swift-4.2.4
func get<T, U>(_ keyPath: KeyPath<T, U>) -> (T) -> (U) { return { value in return value[keyPath: keyPath] } } struct A { let a: Int } let x = get(\A.a) print(x(A(a: 3)))
(edited)
Avatar
swift42 BOT 01-Jun-18 11:10 AM
3
(edited)
Avatar
tarunon 01-Jun-18 11:10 AM
@koher こうですかね。やりたいことはできそう。
Avatar
koher 01-Jun-18 11:14 AM
お、そもそも KeyPath でいい気がしてきました。ありがとうございます🙏🏻
Avatar
tarunon 01-Jun-18 11:15 AM
staticな参照を取る道具を取り回して何かやりたいのかと思った。
Avatar
koher 02-Jun-18 03:48 PM
KeyPath 、ちょっと合ってるか自信ないですが、↓になってほしくないですか?
class Animal { var a: Int = 42 } class Cat : Animal {} let k1: WritableKeyPath<Animal, Int> = \.a let k2: KeyPath<Animal, Int> = k1 // OK let k3: PartialKeyPath<Animal> = k2 // OK let k4: AnyKeyPath = k3 // OK let k1b: WritableKeyPath<Animal, Any> = k1 // NG: これはできなくてよい let k2b: KeyPath<Animal, Any> = k2 // NG: これはできてほしい let k1c: WritableKeyPath<Cat, Int> = k1 // NG: これはできてほしい let k2c: KeyPath<Cat, Int> = k2 // NG: これはできてほしい let k3c: PartialKeyPath<Cat> = k3 // NG: これはできてほしい
15:48
つまり、↓であってほしい気が。
class WritableKeyPath<in Root, Value> : ... { ... } class KeyPath<in Root, out Value> : ... { ... } class PartialKeyPath<in Root> : ... { ... } class AnyKeyPath { ... }
(edited)
Avatar
koher 02-Jun-18 04:36 PM
なんか↓このメソッドおかしくないですか? KeyPathWritableKeyPath を結合しても KeyPath であってほしい気が。 https://developer.apple.com/documentation/swift/keypath/2945102-appending
16:36
リファレンスには記載があるけど実際には使えない? @swiftbot
struct Foo { var a: Int } struct Bar { var foo: Foo } let k1: KeyPath<Bar, Foo> = \.foo let k2: WritableKeyPath<Foo, Int> = \.a let k: WritableKeyPath<Bar, Int> = k1.appending(path: k2)
🛠 1
Avatar
swiftbot BOT 02-Jun-18 04:36 PM
Author icon
koher
struct Foo { var a: Int } struct Bar { var foo: Foo } let k1: KeyPath<Bar, Foo> = \.foo let k2: WritableKeyPath<Foo, Int> = \.a let k: WritableKeyPath<Bar, Int> = k1.appending(path: k2)
Version:
swift-4.1.1-RELEASE
Output:
Error:
/usercode/main.swift:11:39: error: cannot convert value of type 'KeyPath<Bar, Int>' to specified type 'WritableKeyPath<Bar, Int>' let k: WritableKeyPath<Bar, Int> = k1.appending(path: k2) ~~~^~~~~~~~~~~~~~~~~~~ as! WritableKeyPath<Bar, Int>
Avatar
koher 02-Jun-18 04:47 PM
↓ができない(このメソッドがない)のはなぜ? @swiftbot
struct Foo { var a: Int = 42 } struct Bar { var foo: Foo = Foo() } let k1: KeyPath<Bar, Foo> = \.foo let k2: PartialKeyPath<Foo> = \.a let k: PartialKeyPath<Bar> = k1.appending(path: k2)
🛠 1
Avatar
swiftbot BOT 02-Jun-18 04:47 PM
Author icon
koher
struct Foo { var a: Int = 42 } struct Bar { var foo: Foo = Foo() } let k1: KeyPath<Bar, Foo> = \.foo let k2: PartialKeyPath<Foo> = \.a let k: PartialKeyPath<Bar> = k1.appending(path: k2)
Version:
swift-4.1.1-RELEASE
Output:
Error:
/usercode/main.swift:11:49: error: cannot convert value of type 'PartialKeyPath<Foo>' to expected argument type 'ReferenceWritableKeyPath<_, _>' let k: PartialKeyPath<Bar> = k1.appending(path: k2) ^~
Avatar
koher 02-Jun-18 04:49 PM
↓はできるので結合できて問題ない気が。 @swiftbot
struct Foo { var a: Int = 42 } struct Bar { var foo: Foo = Foo() } let k1: KeyPath<Bar, Foo> = \.foo let k2: PartialKeyPath<Foo> = \.a // let k: PartialKeyPath<Bar> = k1.appending(path: k2) let bar = Bar() // let a: Int = bar[keyPath: k1][keyPath: k2] let a: Any = bar[keyPath: k1][keyPath: k2] print(a) // OK: 42
🛠 1
Avatar
swiftbot BOT 02-Jun-18 04:49 PM
Author icon
koher
struct Foo { var a: Int = 42 } struct Bar { var foo: Foo = Foo() } let k1: KeyPath<Bar, Foo> = \.foo let k2: PartialKeyPath<Foo> = \.a // let k: PartialKeyPath<Bar> = k1.appending(path: k2) let bar = Bar() // let a: Int = bar[keyPath: k1][keyPath: k2] let a: Any = bar[keyPath: k1][keyPath: k2] print(a) // OK: 42
Version:
swift-4.1.1-RELEASE
Output:
42
Error:
Avatar
koher 02-Jun-18 05:11 PM
KeyPathWritableKeyPath を append して WritableKeyPath 生成するメソッドが(ドキュメント上?)できてしまってるの↓のせいか。 where 以下がコメントアウト。
extension _AppendKeyPath /* where Self == WritableKeyPath<T,U> */ {
https://github.com/apple/swift/blob/master/stdlib/public/core/KeyPath.swift#L1812
swift - The Swift Programming Language
17:13
swift - The Swift Programming Language
Avatar
koher 02-Jun-18 05:31 PM
(Writable)KeyPathPartialKeyPath を append して PartialKeyPath を得るの、とりあえず無理やりで extension 書けた。 @swiftbot
struct Foo { var a: Int = 42 } struct Bar { var foo: Foo = Foo() } extension KeyPath { func appending(path: PartialKeyPath<Value>) -> PartialKeyPath<Root> { return (self as AnyKeyPath).appending(path: path as AnyKeyPath)! as! PartialKeyPath<Root> } } let k1: WritableKeyPath<Bar, Foo> = \.foo let k2: PartialKeyPath<Foo> = \.a let k: PartialKeyPath<Bar> = k1.appending(path: k2) let bar = Bar() let a: Any = bar[keyPath: k] print(a)
🛠 1
Avatar
swiftbot BOT 02-Jun-18 05:31 PM
Author icon
koher
struct Foo { var a: Int = 42 } struct Bar { var foo: Foo = Foo() } extension KeyPath { func appending(path: PartialKeyPath<Value>) -> PartialKeyPath<Root> { return (self as AnyKeyPath).appending(path: path as AnyKeyPath)! as! PartialKeyPath<Root> } } let k1: WritableKeyPath<Bar, Foo> = \.foo let k2: PartialKeyPath<Foo> = \.a let k: PartialKeyPath<Bar> = k1.appending(path: k2) let bar = Bar() let a: Any = bar[keyPath: k] print(a)
Version:
swift-4.1.1-RELEASE
Output:
42
Error:
Avatar
omochimetaru 02-Jun-18 06:02 PM
厳密に読めてないけどパッと見そのとおりに思える。
Avatar
koher 03-Jun-18 03:41 PM
@swiftbot ↓だと didSet の中で didSet は呼ばれないけど・・・
struct Foo { var count: Int = 0 var a: Int = 42 { didSet { print("Foo.a didSet: \(count)") count += 1 } } } struct Bar { var count: Int = 0 var foo: Foo = Foo() { didSet { print("Bar.foo didSet: \(count), \(foo.count)") count += 1 foo.count += 100 } } } var bar = Bar() bar.foo.a = -1
(edited)
🛠 1
Avatar
swiftbot BOT 03-Jun-18 03:41 PM
(edited)
Author icon
koher
struct Foo { var count: Int = 0 var a: Int = 42 { didSet { print("Foo.a didSet: \(count)") count += 1 } } } struct Bar { var count: Int = 0 var foo: Foo = Foo() { didSet { print("Bar.foo didSet: \(count), \(foo.count)") count += 1 foo.count += 100 } } } var bar = Bar() bar.foo.a = -1
Version:
swift-4.1.1-RELEASE
Output:
Foo.a didSet: 0 Bar.foo didSet: 0, 1
Error:
Avatar
koher 03-Jun-18 03:43 PM
@swiftbot Key Path 経由だと無限再帰・・・。
struct Foo { var count: Int = 0 var a: Int = 42 { didSet { print("Foo.a didSet: \(count)") count += 1 } } } struct Bar { var count: Int = 0 var foo: Foo = Foo() { didSet { print("Bar.foo didSet: \(count), \(foo.count)") count += 1 // foo.count += 100 self[keyPath: \Bar.foo].count += 100 } } } var bar = Bar() bar.foo.a = -1
(edited)
🛠 1
Avatar
swiftbot BOT 03-Jun-18 03:43 PM
(edited)
Author icon
koher
struct Foo { var count: Int = 0 var a: Int = 42 { didSet { print("Foo.a didSet: \(count)") count += 1 } } } struct Bar { var count: Int = 0 var foo: Foo = Foo() { didSet { print("Bar.foo didSet: \(count), \(foo.count)") count += 1 // foo.count += 100 self[keyPath: \Bar.foo].count += 100 } } } var bar = Bar() bar.foo.a = -1
Version:
swift-4.1.1-RELEASE
Output:
Foo.a didSet: 0 Bar.foo didSet: 0, 1 Bar.foo didSet: 1, 101 Bar.foo didSet: 2, 201 Bar.foo didSet: 3, 301 Bar.foo didSet: 4, 401 Bar.foo didSet: 5, 501 Bar.foo didSet: 6, 601 Bar.foo didSet: 7, 701 Bar.foo didSet: 8, 801 Bar.foo didSet: 9, 901 Bar.foo didSet: 10, 1001 Bar.foo didSet: 11, 1101 Bar.foo didSet: 12, 1201 Bar.foo didSet: 13, 1301 Bar.foo didSet: 14, 1401 Bar.foo didSet: 15, 1501 Bar.foo didSet: 16, 1601 Bar.foo didSet: 17, 1701 Bar.foo didSet: 18, 1801 Bar.foo didSet: 19, 1901 Bar.foo didSet: 20, 2001 Bar.foo didSet: 21, 2101 Bar.foo didSet: 22, 2201 Bar.foo didSet: 23, 2301 Bar.foo didSet: 24, 2401 Bar.foo didSet: 25, 2501 Bar.foo didSet: 26, 2601 Bar.foo didSet: 27, 2701 Bar.foo didSet: 28, 2801 Bar.foo didSet: 29, 2901 Bar.foo didSet: 30, 3001 Bar.foo didSet: 31, 3101 Bar.foo didSet: 32, 3201 Bar.foo didSet: 33, 3301 Bar.foo didSet: 34, 3401 Bar.foo didSet: 35, 3501 Bar.foo didSet: 36, 3601 Bar.foo didSet: 37, 3701 Bar.foo didSet: 38, 3801 Bar.foo didSet: 39, 3901 ...
Error:
/usr/bin/swift[0x3f24d64] /usr/bin/swift[0x3f250a6] /lib/x86_64-linux-gnu/libpthread.so.0(+0x11390)[0x7fb6ec227390] /usr/lib/swift/linux/libswiftCore.so(swift_conformsToProtocol+0x3e)[0x7fb6e840373e] /usr/lib/swift/linux/libswiftCore.so(+0x39c05f)[0x7fb6e83f505f] /usr/lib/swift/linux/libswiftCore.so(+0x39b82d)[0x7fb6e83f482d] /usr/lib/swift/linux/libswiftCore.so(+0x2e518a)[0x7fb6e833e18a] Stack dump: 0. Program arguments: /usr/bin/swift -frontend -interpret /usercode/main.swift -disable-objc-interop -I /Libraries/All/.build/release -module-name main -lAll Segmentation fault (core dumped)
15:43
Avatar
swiftbot BOT 03-Jun-18 03:51 PM
Avatar
omochimetaru 04-Jun-18 01:16 AM
countに代入するメソッドを作って、それをsetterの中で呼び出した場合も同じ事になるし、自然だと思います
Avatar
koher 04-Jun-18 01:18 AM
昨日試したときはmutatinf funcで書き換えた場合(多分inoutも)はならなかった。
Avatar
omochimetaru 04-Jun-18 01:20 AM
あれ、マジすか 後で試してみます
Avatar
omochimetaru 04-Jun-18 01:49 AM
@swiftbot
struct Stone { var name: String = "" { didSet { let newValue = name if recCount == 5 { return } recCount += 1 print("name.didSet begin: \(oldValue) -> \(newValue)") update() print("name.didSet end: \(oldValue) -> \(newValue)") } } var recCount = 0 mutating func update() { name = "jiro" } } var b = Stone() b.name = "taro"
🛠 1
Avatar
swiftbot BOT 04-Jun-18 01:49 AM
Author icon
omochimetaru
struct Stone { var name: String = "" { didSet { let newValue = name if recCount == 5 { return } recCount += 1 print("name.didSet begin: \(oldValue) -> \(newValue)") update() print("name.didSet end: \(oldValue) -> \(newValue)") } } var recCount = 0 mutating func update() { name = "jiro" } } var b = Stone() b.name = "taro"
Version:
swift-4.1.1-RELEASE
Output:
name.didSet begin: -> taro name.didSet begin: taro -> jiro name.didSet begin: jiro -> jiro name.didSet begin: jiro -> jiro name.didSet begin: jiro -> jiro name.didSet end: jiro -> jiro name.didSet end: jiro -> jiro name.didSet end: jiro -> jiro name.didSet end: taro -> jiro name.didSet end: -> taro
Error:
Avatar
omochimetaru 04-Jun-18 01:49 AM
@koher やっぱり再入しました。
Avatar
koher 04-Jun-18 02:11 AM
↑で言えば namemutating funcStonedidSet から呼び出した場合の話だった。それだと直接編集するのと同じだから再帰しなくて当然か。
02:12
この再帰を防ぐ良い方法ってないかな?
Avatar
omochimetaru 04-Jun-18 02:12 AM
name.capitalize() みたいな事か。
Avatar
koher 04-Jun-18 02:13 AM
↓こういう場合。 @swiftbot
struct Stone { var name: String = "" { didSet { let newValue = name if recCount == 5 { return } recCount += 1 print("name.didSet begin: \(oldValue) -> \(newValue)") name.append("x") print("name.didSet end: \(oldValue) -> \(newValue)") } } var recCount = 0 } var b = Stone() b.name = "taro"
🛠 1
Avatar
swiftbot BOT 04-Jun-18 02:13 AM
Author icon
koher
struct Stone { var name: String = "" { didSet { let newValue = name if recCount == 5 { return } recCount += 1 print("name.didSet begin: \(oldValue) -> \(newValue)") name.append("x") print("name.didSet end: \(oldValue) -> \(newValue)") } } var recCount = 0 } var b = Stone() b.name = "taro"
Version:
swift-4.1.1-RELEASE
Output:
name.didSet begin: -> taro name.didSet end: -> taro
Error:
Avatar
omochimetaru 04-Jun-18 02:14 AM
この再帰を防ぐ良い方法
自分ならフラグを立ててdidSetの中で分岐します、なるべくそのようなコールフロー自体を排除するようにリファクタリングするけど。
02:14
didSetじゃなくてsetterじゃないと無理かも
Avatar
koher 05-Jun-18 04:56 AM
↓これできてほしい気が。 @swiftbot
struct Foo { var a: Int = 42 } struct Bar { var foo: Foo? = Foo() } var bar = Bar() bar[keyPath: \Bar.foo?.a] = -1 // ⛔ print(bar.foo!.a)
🛠 1
Avatar
swiftbot BOT 05-Jun-18 04:56 AM
Author icon
koher
struct Foo { var a: Int = 42 } struct Bar { var foo: Foo? = Foo() } var bar = Bar() bar[keyPath: \Bar.foo?.a] = -1 // ⛔ print(bar.foo!.a)
Version:
swift-4.1.1-RELEASE
Output:
Error:
/usercode/main.swift:10:27: error: cannot assign to immutable expression of type 'Int?' bar[keyPath: \Bar.foo?.a] = -1 // ⛔
Avatar
koher 05-Jun-18 04:57 AM
もちろん↓はできる。 @swiftbot
struct Foo { var a: Int = 42 } struct Bar { var foo: Foo? = Foo() } var bar = Bar() bar.foo?.a = -1 // ✅ print(bar.foo!.a)
🛠 1
Avatar
swiftbot BOT 05-Jun-18 04:57 AM
Author icon
koher
struct Foo { var a: Int = 42 } struct Bar { var foo: Foo? = Foo() } var bar = Bar() bar.foo?.a = -1 // ✅ print(bar.foo!.a)
Version:
swift-4.1.1-RELEASE
Output:
-1
Error:
Avatar
tarunon 05-Jun-18 04:57 AM
それ確かbugsでも話題になってましたよ
04:58
ObjectiveCだとOptional-chainingなkvcできるのにswiftはできねーじゃんってのが
04:58
あった記憶がある
04:58
RxSwiftとかReactiveCocoaも、それで困ってましたね
Avatar
koher 05-Jun-18 04:58 AM
おお、そうなんですね。できるようになったらいいんですが・・・。
Avatar
koher 05-Jun-18 05:12 AM
05:12
Joe Groff added a comment - 7 Sep 2017 2:49 AM This is by design. You can't write back through optional chains, since there's nowhere to write to if the element is nil.
05:12
😭
05:14
あー、確かに non-nil しか書き戻せないというのを記述不能なのか。
05:15
Jaden Geller and Matthew Johnson suggested some extensions to Optional that could make working with writable key paths more expressive within the current model:
extension Optional { // Produce the `default` value if `self` is nil. subscript(default value: Wrapped) -> Wrapped { get { return self ?? value } set { self = newValue } } // Act like optional chaining on read, while allowing "writes" that drop // the value on the floor if `self` is nil. subscript<T>(droppingWritesOnNil path: WritableKeyPath<Wrapped, T>) -> T? { get { return self?[keyPath: path] } set { if let newValue = newValue { self?[keyPath: path] = newValue } } } }
05:19
↑使ったらネストした KeyPath で記述できました。 @swiftbot
extension Optional { // Produce the `default` value if `self` is nil. subscript(default value: Wrapped) -> Wrapped { get { return self ?? value } set { self = newValue } } // Act like optional chaining on read, while allowing "writes" that drop // the value on the floor if `self` is nil. subscript<T>(droppingWritesOnNil path: WritableKeyPath<Wrapped, T>) -> T? { get { return self?[keyPath: path] } set { if let newValue = newValue { self?[keyPath: path] = newValue } } } } struct Foo { var a: Int = 42 } struct Bar { var foo: Foo? = Foo() } var bar = Bar() bar[keyPath: \Bar.foo[droppingWritesOnNil: \.a]] = -1 print(bar.foo!.a) bar.foo = nil bar[keyPath: \Bar.foo[droppingWritesOnNil: \.a]] = 999 print(String(describing: bar.foo))
(edited)
🛠 1
Avatar
swiftbot BOT 05-Jun-18 05:19 AM
(edited)
Author icon
koher
extension Optional { // Produce the `default` value if `self` is nil. subscript(default value: Wrapped) -> Wrapped { get { return self ?? value } set { self = newValue } } // Act like optional chaining on read, while allowing "writes" that drop // the value on the floor if `self` is nil. subscript<T>(droppingWritesOnNil path: WritableKeyPath<Wrapped, T>) -> T? { get { return self?[keyPath: path] } set { if let newValue = newValue { self?[keyPath: path] = newValue } } } } struct Foo { var a: Int = 42 } struct Bar { var foo: Foo? = Foo() } var bar = Bar() bar[keyPath: \Bar.foo[droppingWritesOnNil: \.a]] = -1 print(bar.foo!.a) bar.foo = nil bar[keyPath: \Bar.foo[droppingWritesOnNil: \.a]] = 999 print(String(describing: bar.foo))
Version:
swift-4.1.1-RELEASE
Output:
-1 nil
Error:
Avatar
koher 05-Jun-18 07:43 AM
値型とイミュータブルクラスしか使ってないのに weak でイミュータビリティが壊れた。 @swiftbot
struct Weak<Value : AnyObject> { weak var value: Value? { didSet { print("Weak.value didSet") } } init(_ value: Value) { self.value = value } } extension Weak : Equatable where Value : Equatable { static func ==(lhs: Weak<Value>, rhs: Weak<Value>) -> Bool { return lhs.value == rhs.value } } extension Weak : Hashable where Value : Hashable { var hashValue: Int { return value?.hashValue ?? 0 } } class Foo : Hashable { static func ==(lhs: Foo, rhs: Foo) -> Bool { return lhs === rhs } var hashValue: Int { return ObjectIdentifier(self).hashValue } } var dict: [Weak<Foo>: Int] = [:] var weak1: Weak<Foo>! var weak2: Weak<Foo>! do { let foo1 = Foo() weak1 = Weak(foo1) dict[weak1] = 111 print("weak1: \(weak1)") let foo2 = Foo() weak2 = Weak(foo2) dict[weak2] = 222 print("weak2: \(weak2)") for (key, value) in dict { print("\(key) -> \(value)") } print("dict[weak1]: \(String(describing: dict[weak1]))") print("dict[weak2]: \(String(describing: dict[weak2]))") } print("---") print("weak1: \(weak1)") print("weak2: \(weak2)") for (key, value) in dict { print("\(key) -> \(value)") } print("dict[weak1]: \(String(describing: dict[weak1]))") print("dict[weak2]: \(String(describing: dict[weak2]))")
(edited)
🛠 1
Avatar
swiftbot BOT 05-Jun-18 07:43 AM
(edited)
Author icon
koher
struct Weak<Value : AnyObject> { weak var value: Value? { didSet { print("Weak.value didSet") } } init(_ value: Value) { self.value = value } } extension Weak : Equatable where Value : Equatable { static func ==(lhs: Weak<Value>, rhs: Weak<Value>) -> Bool { return lhs.value == rhs.value } } extension Weak : Hashable where Value : Hashable { var hashValue: Int { return value?.hashValue ?? 0 } } class Foo : Hashable { static func ==(lhs: Foo, rhs: Foo) -> Bool { return lhs === rhs } var hashValue: Int { return ObjectIdentifier(self).hashValue } } var dict: [Weak<Foo>: Int] = [:] var weak1: Weak<Foo>! var weak2: Weak<Foo>! do { let foo1 = Foo() weak1 = Weak(foo1) dict[weak1] = 111 print("weak1: \(weak1)") let foo2 = Foo() weak2 = Weak(foo2) dict[weak2] = 222 print("weak2: \(weak2)") for (key, value) in dict { print("\(key) -> \(value)") } print("dict[weak1]: \(String(describing: dict[weak1]))") print("dict[weak2]: \(String(describing: dict[weak2]))") } print("---") print("weak1: \(weak1)") print("weak2: \(weak2)") for (key, value) in dict { print("\(key) -> \(value)") } print("dict[weak1]: \(String(describing: dict[weak1]))") print("dict[weak2]: \(String(describing: dict[weak2]))")
Version:
swift-4.1.1-RELEASE
Output:
weak1: Optional(main.Weak<main.Foo>(value: Optional(main.Foo))) weak2: Optional(main.Weak<main.Foo>(value: Optional(main.Foo))) Weak<Foo>(value: Optional(main.Foo)) -> 222 Weak<Foo>(value: Optional(main.Foo)) -> 111 dict[weak1]: Optional(111) dict[weak2]: Optional(222) --- weak1: Optional(main.Weak<main.Foo>(value: nil)) weak2: Optional(main.Weak<main.Foo>(value: nil)) Weak<Foo>(value: nil) -> 222 Weak<Foo>(value: nil) -> 111 dict[weak1]: nil dict[weak2]: nil
Error:
07:43
Avatar
tarunon 05-Jun-18 08:41 AM
破壊しようとしてるようにしか見えないw
😅 1
Avatar
Kishikawa Katsumi 05-Jun-18 08:53 AM
なるほど。これは動作としては私は納得できるけど、どうあるべきなんですかねえ?
08:54
これかな。
08:59
I've argued that we just shouldn't have weak fields in structs at all.
私はまあStructはweakプロパティを持てないとするのは、むしろ良いと思います。
(edited)
Avatar
koher 05-Jun-18 09:00 AM
僕も言語的には structweak プロパティを持てないのがいいんじゃないかと思います。
Avatar
Kishikawa Katsumi 05-Jun-18 09:02 AM
weakはまあ現在のリファレンスカウントの仕組みによるものだから、クラスについてもweak自体を無くしてしまうことができたらそれが一番なんですけどね。
Avatar
koher 05-Jun-18 09:03 AM
うーん、 weak は GC であっても必要になるんじゃないでしょうか?
Avatar
Kishikawa Katsumi 05-Jun-18 09:03 AM
相互参照していると解放できないっていうのを解決しよう。
Avatar
tarunon 05-Jun-18 09:03 AM
GCすなぁ
Avatar
koher 05-Jun-18 09:03 AM
相互参照しないように使うケースは多いですが、それ以外でほしいこともあると思います。
Avatar
tarunon 05-Jun-18 09:04 AM
個人的には今のrefcountは何だかんだ言いつつも好きです。
Avatar
koher 05-Jun-18 09:05 AM
GC の Java でも↓とかありますし。 https://docs.oracle.com/javase/7/docs/api/java/util/WeakHashMap.html
Avatar
Kishikawa Katsumi 05-Jun-18 09:06 AM
Javaのように型でやればいいんじゃないかな。
Avatar
koher 05-Jun-18 09:07 AM
Avatar
Kishikawa Katsumi 05-Jun-18 09:07 AM
そうですね。まあ、これは現状の仕組みを解決できたらという前提の話だから、夢ですけど。
Avatar
koher 05-Jun-18 09:08 AM
ref count 自体は CoW を考えても必要そうですね。
Avatar
tarunon 05-Jun-18 09:08 AM
JavaのGC周りはおもちが面白い話し合ったはず
09:09
Weak指定したのに壊れるとかその辺 (edited)
09:10
Rustの型はかなり強力に生存期間を指定できるので魅力的ですね
Avatar
koher 05-Jun-18 09:10 AM
ref count ベースのままサイクルコレクターを入れるという手もありますが、パフォーマンスとのトレードオフになりローレベルでは許容できず、 2 系統作ることは分断を招くのでやらないというようなことを、たしか IBM での Chris Lattner のトークで言ってました。
Avatar
tarunon 05-Jun-18 09:10 AM
evolutionでも明記されてますね
Avatar
Kishikawa Katsumi 05-Jun-18 09:17 AM
ライブラリレベルで導入できる何かとかないかな。
パフォーマンスとのトレードオフになりローレベルでは許容できず
^ はまあ理解するけど、その一方で、モバイルアプリ開発においては圧倒的に問題は解放されないか意図しない解放なので、そこのパフォーマンスは重要ではないし。。。
Avatar
koher 05-Jun-18 09:33 AM
実際書かれてるコードの 90% で不便を強いられてるのが辛いのはありますよね〜。
Avatar
omochimetaru 05-Jun-18 01:25 PM
なるほど~weakがnilになるから壊れるのか
Avatar
koher 06-Jun-18 01:58 AM
↓みたいな KeyPath のパターンマッチしたくないですか?今だと KeyPath から構成要素を取り出す方法がないので。
struct Foo { var values: [Int] = [2, 3, 5] } let foo = Foo() let path = \Foo.values[0] print(foo[keyPath: path]) switch path { case \Foo.values[let i]: print(i) default: print("default") }
Avatar
norio_nomura 07-Jun-18 03:51 AM
メソッドの別名を定義したいのだけれど、デフォルトパラメータを用意したい場合にはラッパーメソッドを作るしかないのだろうか?
import Foundation func darwinStyleFoo(_ size: Int = 32) { print("darwin style foo") } func unknownStyleFoo(_ size: Int = 32) { print("unknown style foo") } #if _runtime(_ObjC) let foo = darwinStyleFoo #else let foo = unknownStyleFoo #endif foo(32) //OK // foo() // NG
Avatar
omochimetaru 07-Jun-18 03:52 AM
クロージャに代入するとデフォルトパラメータなかったことになりますよね
Avatar
norio_nomura 07-Jun-18 03:54 AM
@_silgen(…)みたいな裏技は無いかなあ。
Avatar
omochimetaru 07-Jun-18 03:54 AM
import Foundation func darwinStyleFoo(_ size: Int) { print("darwin style foo") } func unknownStyleFoo(_ size: Int) { print("unknown style foo") } #if _runtime(_ObjC) let _foo = darwinStyleFoo #else let _foo = unknownStyleFoo #endif func foo(_ size: Int = 32) { _foo(size) }
こういうスタイルはどうですか?
03:54
(裏技は知らないです
Avatar
norio_nomura 07-Jun-18 03:56 AM
スタックトレースを出力するメソッドでdarwinとLinuxで挙動を変えようとしているのですが、ラッパーを挟むとその分スタックトレースが増えるのですよね。
Avatar
omochimetaru 07-Jun-18 03:58 AM
なるほど、う〜ん。。
Avatar
koher 07-Jun-18 04:23 AM
インライン化するとどうなりますか?
Avatar
norio_nomura 07-Jun-18 04:24 AM
インライン化だけを制御する属性って4.2からですよね。
Avatar
tarunon 07-Jun-18 04:24 AM
こういうのはカリー化したらやりたいことできる様になるイメージ
Avatar
norio_nomura 07-Jun-18 04:25 AM
APIデザインをガラッと変えるかな。
04:26
一つのメソッドで挙動を変えるパラメータを持たせて、それらのデフォルトをプラットフォームによって変える、みたいな。
Avatar
koher 07-Jun-18 04:32 AM
- darwinStyleFoounknownStyleFoo は明示的にどちらも呼べるようにしたい - どちらもデフォルト引数を設定したい - foo を呼ぶとプラットフォームによって適切な方が呼ばれるようにしたい(その場合でもデフォルト引数を設定したい) - foo を呼んだ場合でもスタックトレースは darwinStyleFoo 等と同じにしたい (edited)
04:33
とすると、 gyb 等で darwinStyleFoo 等のコードを foo の中にも展開するとかでしょうか・・・。
Avatar
norio_nomura 07-Jun-18 04:34 AM
そうなりますね。
04:36
現状のデザインが良くないみたいなので、変えてみます。 (edited)
04:36
ありがとうございました。
Avatar
omochimetaru 07-Jun-18 04:37 AM
一段多くてもよくて、そのライブラリの分は勝手に消しちゃうとか?
Avatar
koher 07-Jun-18 04:39 AM
@omochimetaru そう単純にはいかない気が。
04:40
仮に [StackTraceElement] がとれて間の一つを取り除けたとしても、 foo を呼び出しているのにその次が darwinStyleFoo になって整合性が崩れそう。
Avatar
tarunon 07-Jun-18 04:59 AM
あーそうだ
05:00
デフォルト引数なんですが、Staticなパラメータ参照出来るので
05:00
class X { static let defaultArgument = 1 func foo(_ bar: Int = defaultArgument) { ... } }
こういうのいけるはず
Avatar
norio_nomura 08-Jun-18 03:06 AM
Staticなパラメータ参照出来るので
とても役に立ちました。ありがとうございます。
03:07
このdefault2Generic parameter 'T' could not be inferredとなる理由が分からない。 @swift-4.2.4
import Foundation infix operator ∘ : CompositionPrecedence precedencegroup CompositionPrecedence { associativity: left higherThan: TernaryPrecedence } public struct Converter<T, U> { public typealias Handler = (T) -> U let handler: Handler public init(_ handler: @escaping Handler) { self.handler = handler } public func compose<A>(_ other: Converter<A, T>) -> Converter<A, U> { return .init { self.handler(other.handler($0)) } } public static func ∘ <A, B, C>(_ lhs: Converter<B, C>, _ rhs: Converter<A, B>) -> Converter<A, C> { return .init { lhs.handler(rhs.handler($0)) } } } public typealias Symbol = (String, String) public typealias Demangler = Converter<Symbol, Symbol> public typealias SymbolFormatter = Converter<Symbol, String> // Demangler extension Converter where T == Symbol, U == Symbol { #if os(macOS) public static let `default` = Converter { ($0.0.uppercased(), $0.1) } #elseif os(Linux) public static let `default` = Converter { ($0.0.lowercased(), $0.1) } #endif } // SymbolFormatter extension Converter where T == Symbol, U == String { #if os(macOS) public static let defaultStyle = Converter { "macOS: \($0)" } #elseif os(Linux) public static let defaultStyle = Converter { "linux: \($0)" } #endif public static let default1 = SymbolFormatter.defaultStyle.compose(Demangler.default) public static let default2 = SymbolFormatter.defaultStyle ∘ Demangler.default }
(edited)
Avatar
swift42 BOT 08-Jun-18 03:08 AM
exit status: 1 with stderr:
<stdin>:49:63: error: generic parameter 'T' could not be inferred public static let default2 = SymbolFormatter.defaultStyle ∘ Demangler.default <stdin>:22:24: note: in call to operator '∘' public static func ∘ <A, B, C>(_ lhs: Converter<B, C>, _ rhs: Converter<A, B>) -> Converter<A, C> {
(edited)
Avatar
norio_nomura 08-Jun-18 04:15 AM
わかった。これで通った。
public static func ∘ <A>(_ lhs: Converter<T, U>, _ rhs: Converter<A, T>) -> Converter<A, U> { return .init { lhs.handler(rhs.handler($0)) } }
Avatar
omochimetaru 08-Jun-18 04:16 AM
ああ。
04:16
型自体のT, Uを使うべきところで、A, B, C を定義しちゃったから、 TとUが解決しなかったんですね。
Avatar
norio_nomura 08-Jun-18 04:16 AM
でした。
Avatar
omochimetaru 08-Jun-18 04:17 AM
static func が 型パラメータの支配下にあるの、忘れがち。僕もそれたまにやります。
04:17
見てたけど推論のバグとかかと思って気づけなかった。。
Avatar
koher 08-Jun-18 04:34 AM
@swiftbot
let a: Range<Int> = 1..<10 print(a.map { $0 * 2 })
🛠 1
Avatar
swiftbot BOT 08-Jun-18 04:34 AM
Author icon
koher
let a: Range<Int> = 1..<10 print(a.map { $0 * 2 })
Version:
swift-4.1.1-RELEASE
Output:
Error:
/usercode/main.swift:2:7: error: value of type 'Range<Int>' has no member 'map' print(a.map { $0 * 2 }) ^ ~~~
Avatar
koher 08-Jun-18 04:35 AM
↑何か間違えてますっけ?なんかアホなミスしてそう・・・。
Avatar
omochimetaru 08-Jun-18 04:35 AM
Rangeにmapはないのでは
Avatar
omochimetaru 08-Jun-18 04:36 AM
あー CountableRangeならCollectionとしてmapできるか。
Avatar
koher 08-Jun-18 04:36 AM
SequenceCollection を conform してる。
04:36
ん? RangeSequence じゃないのか。
04:37
Swift 4.1 だと。
Avatar
omochimetaru 08-Jun-18 04:37 AM
4.1はまだCountableRangeとRangeがある?
04:37
CountableRangeがc.c.でtypealiasになるのは4.2?
Avatar
koher 08-Jun-18 04:37 AM
そのはず。
Avatar
omochimetaru 08-Jun-18 04:37 AM
じゃあ、それですね。
Avatar
koher 08-Jun-18 04:37 AM
ドキュメントが先行してるから騙された。
Avatar
omochimetaru 08-Jun-18 04:38 AM
[2, 4, 6, 8, 10, 12, 14, 16, 18]
04:38
Avatar
koher 08-Jun-18 04:38 AM
↓は問題なかった。 @swiftbot
let a: CountableRange<Int> = 1..<10 print(a.map { $0 * 2 })
🛠 1
Avatar
swiftbot BOT 08-Jun-18 04:38 AM
Author icon
koher
let a: CountableRange<Int> = 1..<10 print(a.map { $0 * 2 })
Version:
swift-4.1.1-RELEASE
Output:
[2, 4, 6, 8, 10, 12, 14, 16, 18]
Error:
Avatar
omochimetaru 08-Jun-18 04:38 AM
@swiftbot versions
Avatar
swiftbot BOT 08-Jun-18 04:38 AM
2018-05-29-a 2018-05-08-a 2018-05-02-a 2018-04-25-a 2018-04-23-a 4.1.1 4.1 4.0.3 4.0.2 4.0 3.1.1 3.1 3.0.2 3.0.1
Avatar
omochimetaru 08-Jun-18 04:38 AM
@swiftbot --version=2018-05-29-a
let a: Range<Int> = 1..<10 print(a.map { $0 * 2 })
🛠 1
Avatar
swiftbot BOT 08-Jun-18 04:38 AM
Author icon
omochimetaru
let a: Range<Int> = 1..<10 print(a.map { $0 * 2 })
Version:
swift-4.2-DEVELOPMENT-SNAPSHOT-2018-05-29-a
Output:
[2, 4, 6, 8, 10, 12, 14, 16, 18]
Error:
Avatar
omochimetaru 08-Jun-18 04:38 AM
うむ
🙏 1
Avatar
koher 12-Jun-18 07:26 AM
↓おもしろ。 @swiftbot
extension Never: Equatable { public static func == (lhs: Never, rhs: Never) -> Bool { switch (lhs, rhs) { } } } let a: [Never] = [] print(a == a) // OK
https://github.com/apple/swift-evolution/blob/master/proposals/0215-conform-never-to-hashable-and-equatable.md
(edited)
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
🛠 1
Avatar
swiftbot BOT 12-Jun-18 07:26 AM
(edited)
Author icon
koher
extension Never: Equatable { public static func == (lhs: Never, rhs: Never) -> Bool { switch (lhs, rhs) { } } } let a: [Never] = [] print(a == a) // OK
Version:
swift-4.1.1-RELEASE
Output:
true
Error:
Avatar
koher 12-Jun-18 07:28 AM
Never なので switch の中が空で OK 。 -> Bool だけど return がなくて OK 。
😮 2
Avatar
omochimetaru 12-Jun-18 07:35 AM
@swiftbot
func a(a: Int, b: String, c: Never) -> Float { }
🛠 1
Avatar
swiftbot BOT 12-Jun-18 07:35 AM
Author icon
omochimetaru
func a(a: Int, b: String, c: Never) -> Float { }
Version:
swift-4.1.1-RELEASE
Output:
Error:
/usercode/main.swift:2:1: error: missing return in a function expected to return 'Float' } ^
Avatar
omochimetaru 12-Jun-18 07:35 AM
あれ?
07:36
引数に Neverを含む関数は絶対に呼び出せないからreturnいらないのかと思った。
Avatar
norio_nomura 12-Jun-18 09:22 AM
おー、これってinamyさんあたりが何かで発表してたのを見た気がする。
Avatar
koher 12-Jun-18 09:34 AM
どうせだったら Error も付けてほしいですよね。 EquatableHashable だけでなくて。
09:34
そうすれば bottom type にならなくても大分使いやすくなる。
09:34
ってか、付けれるのか。今でも。 (edited)
09:36
@swiftbot
extension Never : Error {} enum Result<T, E: Error> { case success(T) case failue(E) } let a: Result<Int, Never> = .success(42) print(a)
🛠 1
Avatar
swiftbot BOT 12-Jun-18 09:36 AM
Author icon
koher
extension Never : Error {} enum Result<T, E: Error> { case success(T) case failue(E) } let a: Result<Int, Never> = .success(42) print(a)
Version:
swift-4.1.1-RELEASE
Output:
success(42)
Error:
Avatar
koher 12-Jun-18 09:37 AM
NoError じゃなくても Never : Error 自分で後付でもいいのか。
Avatar
tarunon 12-Jun-18 02:46 PM
これできるならResultで対応してNoErrorをNeverのaliasにしてほしいなぁ
Avatar
ikesyo 12-Jun-18 03:12 PM
うーんstdlib側でNever: Errorになるならいいですけど、stdlibで準拠させてないprotocolにライブラリがextensionで準拠させるのは僕は気乗りしないですねー。各自が自分のアプリコードでやる分にはいいと思うけど。
15:12
ということでそのevolutionのレビュー期間中にコメントするとよさそうですね (edited)
Avatar
tarunon 12-Jun-18 03:13 PM
レビュー期間中なのか
Avatar
ikesyo 12-Jun-18 03:14 PM
Active review (June 12...19)
🙏 1
15:17
AuthorがReactiveSwiftやCarthageのmdiepです
Avatar
tarunon 12-Jun-18 03:23 PM
これざっと読むとError==Neverとか書いてあるのでそれやるなら…みたいなところはある
15:23
議論元も読んでみよう
Avatar
ikesyo 13-Jun-18 05:58 AM
Never could also conform to the Error protocol.
If we're cherry-picking protocols to conform Never to, Error seems like another good one to whitelist, since it's useful to use Never to close off the error path in Result-like abstractions.
05:59
Moderate -1. Never is special because it has no instances - it is uninhabited by design. This means that it can conform to all protocols. I'd rather see a global solution rather than cherry picking these two specific protocols. Also, in the discussion of Never, it was poi...
Avatar
tarunon 13-Jun-18 06:44 AM
全然関係ないけどEquatableが気軽に定義できるようになったのめちゃくちゃ嬉しいですね
🙂 1
Avatar
omochimetaru 13-Jun-18 06:44 AM
自動生成?
Avatar
tarunon 13-Jun-18 06:45 AM
そう。最近妙に捗るなと思ったら下手したらCondConfよりこっちのほうがコードベースに効いてる
Avatar
omochimetaru 13-Jun-18 06:46 AM
適用箇所多いなら大きいよね
Avatar
omochimetaru 14-Jun-18 03:06 AM
@swiftbot
struct Cat { var name: String? func nya() { if let name = name { print(name) } } }
🛠 1
Avatar
swiftbot BOT 14-Jun-18 03:06 AM
Author icon
omochimetaru
struct Cat { var name: String? func nya() { if let name = name { print(name) } } }
Version:
swift-4.1.1-RELEASE
Output:
Error:
Avatar
omochimetaru 14-Jun-18 03:07 AM
@swiftbot versions
Avatar
swiftbot BOT 14-Jun-18 03:07 AM
2018-05-29-a 2018-05-08-a 2018-05-02-a 2018-04-25-a 2018-04-23-a 4.1.1 4.1 4.0.3 4.0.2 4.0 3.1.1 3.1 3.0.2 3.0.1
Avatar
omochimetaru 14-Jun-18 03:07 AM
@swiftbot --version=3.0.2,3.1.1,4.0.3
struct Cat { var name: String? func nya() { if let name = name { print(name) } } }
🛠 1
Avatar
swiftbot BOT 14-Jun-18 03:07 AM
Author icon
omochimetaru
struct Cat { var name: String? func nya() { if let name = name { print(name) } } }
Version:
swift-3.0.2-RELEASE
Output:
Error:
Version:
swift-3.1.1-RELEASE
Output:
Error:
Version:
swift-4.0.3-RELEASE
Output:
Error:
Avatar
omochimetaru 14-Jun-18 03:08 AM
if let name = self.name { } じゃないといけなかった気がするんだけど勘違い・・・?
Avatar
norio_nomura 14-Jun-18 03:56 AM
その場合、ずっとselfは不要だったと思う。
Avatar
omochimetaru 14-Jun-18 03:59 AM
うーむ、なるほど。
Avatar
Kishikawa Katsumi 14-Jun-18 04:37 AM
if letのパターンは大丈夫だっと思いますね。
Avatar
omochimetaru 14-Jun-18 04:38 AM
struct Cat { func name() -> String { return "tama" } func nya() { let name = self.name() } }
04:38
これだ、これと混ざってた。 (edited)
Avatar
Kishikawa Katsumi 14-Jun-18 04:38 AM
関数と同じ名前の変数は怒られる。
Avatar
omochimetaru 14-Jun-18 04:38 AM
struct Cat { func name() -> String? { return "tama" } func nya() { if let name = name() {} } }
04:39
↑こうだといける。
04:39
let var = expif let var = exp では 右辺と左辺の名前衝突ルールが違うんですね。
Avatar
koher 18-Jun-18 05:08 AM
EasyImagy 楽だ🙂
var image: Image<RGBA<UInt8>> = Image(nsImage: imageView.image!) image = Image(image[1000..<1640, 1000..<1640]) imageView.image! = image.nsImage
Avatar
t.ae 21-Jun-18 01:36 AM
@swiftbot
import Foundation class UDPSocket { let queue = DispatchQueue(label: "socket") let socket = Socket() func noreturn() { queue.async { [weak self] in let socket = self!.socket socket.noreturn() } } deinit { socket.canceled = true print("UDPSocket deinit.") } } class Socket { var canceled = false func noreturn() { while !canceled { } } deinit { print("Socket deinit.") } } var udp: UDPSocket? = UDPSocket() udp!.noreturn() sleep(1) udp = nil sleep(1)
(edited)
🛠 1
Avatar
swiftbot BOT 21-Jun-18 01:36 AM
(edited)
Author icon
t.ae
import Foundation class UDPSocket { let queue = DispatchQueue(label: "socket") let socket = Socket() func noreturn() { queue.async { [weak self] in let socket = self!.socket socket.noreturn() } } deinit { socket.canceled = true print("UDPSocket deinit.") } } class Socket { var canceled = false func noreturn() { while !canceled { } } deinit { print("Socket deinit.") } } var udp: UDPSocket? = UDPSocket() udp!.noreturn() sleep(1) udp = nil sleep(1)
Version:
swift-4.1.1-RELEASE
Output:
UDPSocket deinit. Socket deinit.
Error:
01:36
Avatar
t.ae 21-Jun-18 01:38 AM
@swiftbot
import Foundation class UDPSocket { let queue = DispatchQueue(label: "socket") let socket = Socket() func noreturn() { queue.async { [weak self] in // let socket = self!.socket self?.socket.noreturn() } } deinit { socket.canceled = true print("UDPSocket deinit.") } } class Socket { var canceled = false func noreturn() { while !canceled { } } deinit { print("Socket deinit.") } } var udp: UDPSocket? = UDPSocket() udp!.noreturn() sleep(1) udp = nil sleep(1)
🛠 1
Avatar
swiftbot BOT 21-Jun-18 01:38 AM
Author icon
t.ae
import Foundation class UDPSocket { let queue = DispatchQueue(label: "socket") let socket = Socket() func noreturn() { queue.async { [weak self] in // let socket = self!.socket self?.socket.noreturn() } } deinit { socket.canceled = true print("UDPSocket deinit.") } } class Socket { var canceled = false func noreturn() { while !canceled { } } deinit { print("Socket deinit.") } } var udp: UDPSocket? = UDPSocket() udp!.noreturn() sleep(1) udp = nil sleep(1)
Version:
swift-4.1.1-RELEASE
Output:
Error:
Avatar
t.ae 21-Jun-18 01:39 AM
上の2つで片方リークしてるんですがどう違うんですかね・・・
Avatar
omochimetaru 21-Jun-18 01:39 AM
無限ループが静的に確定して最適化で壊れてるんじゃない?
Avatar
t.ae 21-Jun-18 01:40 AM
というと?
Avatar
omochimetaru 21-Jun-18 01:42 AM
あれ?出力結果が変わった。
01:42
クラッシュしてたように見えた。
Avatar
t.ae 21-Jun-18 01:43 AM
fatalerrorしてたのはキューに投げたタスク以前にudp = nilが走ってるみたいだったのでsleepいれました (edited)
Avatar
omochimetaru 21-Jun-18 01:46 AM
ああ、わかった
01:46
おそらく self?.hoge.fuga() この式は
01:47
if let sself = self { sself.hoge.fuga() }
こう展開されてる。
Avatar
t.ae 21-Jun-18 01:47 AM
そこで捕まるくらいしか考えられないなとは思ってたんですけど
01:49
実行はfugaに移ってるわけで、そこではselfとしてhogeをもってますがsselfへの参照が残ってるのはどういうことなんでしょうか?
01:49
if let sself = self { let hoge = sself.hoge hoge.fuga() }
Avatar
omochimetaru 21-Jun-18 01:49 AM
そうはなってないんだろうね
01:49
式を構成するオブジェクトはその式が終了するまで生きてると思う。
Avatar
t.ae 21-Jun-18 01:50 AM
なるほど・・・
01:50
[weak self]してれば安心と思ってたんですがそうでもないですね
Avatar
omochimetaru 21-Jun-18 01:50 AM
いや
01:50
シングルスレッドならこれで問題は起こらない
01:51
構成してる状況がかなり特殊な条件だと思う (edited)
01:52
クロージャの中で self?. を使うと
01:52
1行目は実行されたけど2行目では解放されてた、みたいな
01:52
実行のバリエーションが増えちゃうから
01:53
冒頭でguard letして意識して制御するほうが無難なことが多いと思う
01:53
今回もそうしてれば不思議な事は起こらないし
01:53
「[weak self] + guard let 」で概ね安心できそう。
Avatar
t.ae 21-Jun-18 01:54 AM
いや今回は冒頭sselfはまずくって
Avatar
rintaro 21-Jun-18 01:54 AM
if let sself = self { sself.hoge.fuga() }
という展開だとしたら、 sself が強参照もってしまうので、だめじゃないですか?
Avatar
t.ae 21-Jun-18 01:54 AM
noreturnなので捕まり続けてしまう
Avatar
omochimetaru 21-Jun-18 01:54 AM
hogeが stored property で fuga が mutating func だった場合
01:54
sselfのsetterを介した書き戻しの必要もあるので
01:55
一般的なコード生成を考えると自然に思う
01:56
あ、まあこの制御の場合はそうね > noreturnなので捕まり続けてしまう
Avatar
rintaro 21-Jun-18 01:56 AM
多分今回の正解は、
queue.async { [weak socket] in socket?.noreturn() }
Avatar
hironytic 21-Jun-18 01:57 AM
冒頭でguard letしても今回はどうしようもなさそうな。。。
Avatar
omochimetaru 21-Jun-18 01:58 AM
あーなので、言いたかったのは 多くのパターンでは weak self + guard let で良くて 今回のキューに無限ループを入れるような特殊なシチュエーションは、 その多くのパターンには当てはまらない って整理するのがよいのでは、と。 @t.ae
Avatar
t.ae 21-Jun-18 01:58 AM
はい。
Avatar
omochimetaru 21-Jun-18 01:58 AM
例えばこれ、while ループさせずに、Queueにasyncの投げ直しを繰り返して
01:58
ループ自体はQueueで担保して、ブロックするクロージャは入れない形に書き換えられて
01:58
そうしていたなら 冒頭guard letでもこの問題を踏まなかったと思う
Avatar
t.ae 21-Jun-18 01:59 AM
ですね。ただここのnoreturnはrecvfromを想定しているのでこの形で書いています。
Avatar
omochimetaru 21-Jun-18 01:59 AM
ああブロックする関数をキューにいれた場合の挙動を前提にやってるのか。
02:00
多分今回の正解は、
元の意図の流れで書くならりんたろさんの↑がシンプルでいいですね
Avatar
t.ae 21-Jun-18 02:00 AM
[weak socket]は良さそうですが他にselfのプロパティを使う場合には[weak self]も足すか個別にキャプチャするか迷いそうですね
Avatar
omochimetaru 21-Jun-18 02:01 AM
queue.async { [weak self] in let socket = self?.socket socket.noreturn() }
👌 2
Avatar
t.ae 21-Jun-18 02:01 AM
socketをキャプチャする場合は[socket]でもいいのかな
Avatar
omochimetaru 21-Jun-18 02:01 AM
もろもろ踏まえて書くなら↑こうかな?
Avatar
hironytic 21-Jun-18 02:01 AM
同じものを書こうとしてた。
Avatar
omochimetaru 21-Jun-18 02:02 AM
socketをキャプチャする場合は[socket]でもいいのかな
それだとキューの発火後にselfがdeinitされてる場合の挙動が変わるけどね。
Avatar
t.ae 21-Jun-18 02:02 AM
確かに
Avatar
omochimetaru 21-Jun-18 02:02 AM
ただここで一回 self?.socket で切ってる事に
02:02
そこまで重要な意味があることがコードから読み取れ無さそうだから
02:03
コメント書いておきたいね・・
🙂 2
Avatar
t.ae 21-Jun-18 02:05 AM
コメント書いておきます。ありがとうございました。
Avatar
hironytic 21-Jun-18 02:07 AM
面白いなー。これはハマったとき悩みそう。
Avatar
rintaro 21-Jun-18 02:08 AM
最適化かけると早期に開放されたりして動作変わっちゃうかもしれないですね。
😳 1
Avatar
omochimetaru 21-Jun-18 02:08 AM
あ〜〜 たしかに・・・
Avatar
kitasuke 23-Jun-18 07:43 AM
SILの質問です。closureのSILを見て遊んでたら気づいたんですが、strong_retainstrong_releaseはペアになってないときもあるんですか?strong_retainは1回しか呼ばれてないのにstrong_releaseは2回呼ばれている
func foo() -> Int { var i = 1 let closure: ((Int) -> Void) = { _ in } closure(10) return i }
// foo() sil hidden @$S7sample23fooSiyF : $@convention(thin) () -> Int { bb0: %0 = alloc_stack $Int, var, name "i" // users: %3, %13 %1 = integer_literal $Builtin.Int64, 1 // user: %2 %2 = struct $Int (%1 : $Builtin.Int64) // users: %14, %3 store %2 to %0 : $*Int // id: %3 // function_ref closure #1 in foo() %4 = function_ref @$S7sample23fooSiyFySicfU_ : $@convention(thin) (Int) -> () // user: %5 %5 = thin_to_thick_function %4 : $@convention(thin) (Int) -> () to $@callee_guaranteed (Int) -> () // users: %12, %11, %10, %7, %6 debug_value %5 : $@callee_guaranteed (Int) -> (), let, name "closure" // id: %6 strong_retain %5 : $@callee_guaranteed (Int) -> () // id: %7 %8 = integer_literal $Builtin.Int64, 10 // user: %9 %9 = struct $Int (%8 : $Builtin.Int64) // user: %10 %10 = apply %5(%9) : $@callee_guaranteed (Int) -> () strong_release %5 : $@callee_guaranteed (Int) -> () // id: %11 strong_release %5 : $@callee_guaranteed (Int) -> () // id: %12 dealloc_stack %0 : $*Int // id: %13 return %2 : $Int // id: %14 } // end sil function '$S7sample23fooSiyF'
Avatar
norio_nomura 23-Jun-18 09:47 AM
thin_to_thick_functionretainされたモノを返すのでは。
09:52
@swift-4.2.4 -Xfrontend -emit-sil
_ = { (_: Int) -> Void in }
Avatar
swift42 BOT 23-Jun-18 09:52 AM
sil_stage canonical import Builtin import Swift import SwiftShims // main sil @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 { bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>): // function_ref closure #1 in %2 = function_ref @$S4mainySicfU_ : $@convention(thin) (Int) -> () // user: %3 %3 = thin_to_thick_function %2 : $@convention(thin) (Int) -> () to $@callee_guaranteed (Int) -> () // user: %4 strong_release %3 : $@callee_guaranteed (Int) -> () // id: %4 %5 = integer_literal $Builtin.Int32, 0 // user: %6 %6 = struct $Int32 (%5 : $Builtin.Int32) // user: %7 return %6 : $Int32 // id: %7 } // end sil function 'main' // closure #1 in sil private @$S4mainySicfU_ : $@convention(thin) (Int) -> () { // %0 // user: %1 bb0(%0 : $Int): debug_value %0 : $Int // id: %1 %2 = tuple () // user: %3 return %2 : $() // id: %3 } // end sil function '$S4mainySicfU_'
Avatar
kitasuke 23-Jun-18 10:12 AM
thin_to_thick_functionか。ドキュメントを探すとそれっぽい記述が見つかりました。@ callee_guaranteedが@convention(thick)を示しているの知らなかったので気づきませんでした。ありがとうございます!
@convention(thick) indicates a "thick" function reference, which uses the Swift calling convention and carries a reference-counted context object used to represent captures or other state required by the function. This attribute is implied by @callee_owned or @callee_guaranteed.
(edited)
Avatar
koher 25-Jun-18 05:23 AM
@swiftbot ↓警告が出る。
extension Optional { @_specialize(exported: true, where Wrapped == Int, S == [Int]) func foo<S : Sequence>(_ sequence: S) -> [Wrapped] where S.Element == Wrapped { return Array(sequence) + (self.map { [$0] } ?? []) } }
🛠 1
Avatar
swiftbot BOT 25-Jun-18 05:23 AM
Author icon
koher
extension Optional { @_specialize(exported: true, where Wrapped == Int, S == [Int]) func foo<S : Sequence>(_ sequence: S) -> [Wrapped] where S.Element == Wrapped { return Array(sequence) + (self.map { [$0] } ?? []) } }
Version:
swift-4.1.1-RELEASE
Output:
Error:
/usercode/main.swift:2:48: warning: redundant same-type constraint 'Wrapped' == 'Int' @_specialize(exported: true, where Wrapped == Int, S == [Int]) ^ /usercode/main.swift:2:58: note: same-type constraint 'S.Element' == 'Int' implied here @_specialize(exported: true, where Wrapped == Int, S == [Int]) ^
Avatar
koher 25-Jun-18 05:24 AM
@swiftbot 冗長な部分を消すとエラーになる。
extension Optional { @_specialize(exported: true, where Wrapped == Int) func foo<S : Sequence>(_ sequence: S) -> [Wrapped] where S.Element == Wrapped { return Array(sequence) + (self.map { [$0] } ?? []) } }
🛠 1
Avatar
swiftbot BOT 25-Jun-18 05:24 AM
Author icon
koher
extension Optional { @_specialize(exported: true, where Wrapped == Int) func foo<S : Sequence>(_ sequence: S) -> [Wrapped] where S.Element == Wrapped { return Array(sequence) + (self.map { [$0] } ?? []) } }
Version:
swift-4.1.1-RELEASE
Output:
Error:
/usercode/main.swift:2:6: error: too few type parameters are specified in '_specialize' attribute (got 1, but expected 2) @_specialize(exported: true, where Wrapped == Int) ^ /usercode/main.swift:2:6: error: Missing constraint for 'S' in '_specialize' attribute @_specialize(exported: true, where Wrapped == Int) ^
Avatar
koher 25-Jun-18 05:24 AM
@swiftbot もう一つの方を消しても同じくエラー。
extension Optional { @_specialize(exported: true, where S == [Int]) func foo<S : Sequence>(_ sequence: S) -> [Wrapped] where S.Element == Wrapped { return Array(sequence) + (self.map { [$0] } ?? []) } }
🛠 1
Avatar
swiftbot BOT 25-Jun-18 05:24 AM
Author icon
koher
extension Optional { @_specialize(exported: true, where S == [Int]) func foo<S : Sequence>(_ sequence: S) -> [Wrapped] where S.Element == Wrapped { return Array(sequence) + (self.map { [$0] } ?? []) } }
Version:
swift-4.1.1-RELEASE
Output:
Error:
/usercode/main.swift:2:6: error: too few type parameters are specified in '_specialize' attribute (got 1, but expected 2) @_specialize(exported: true, where S == [Int]) ^ /usercode/main.swift:2:6: error: Missing constraint for 'Wrapped' in '_specialize' attribute @_specialize(exported: true, where S == [Int]) ^
Avatar
koher 25-Jun-18 05:25 AM
これは警告が出る条件判定のコンパイラのバグ?
Avatar
omochimetaru 25-Jun-18 05:25 AM
func の方を消すのはどうなりますか?
Avatar
koher 25-Jun-18 05:25 AM
func の方を消すってどういうこと?
Avatar
omochimetaru 25-Jun-18 05:25 AM
specializeの中身と func文のwhere句が冗長なのかなって思って。
Avatar
koher 25-Jun-18 05:26 AM
それはできなくない?
05:27
条件が変わってしまう。
05:28
@swiftbot funcwhere を消すと↓ WrapedS.Element が同じ型である保証がなくなって + ができない。
extension Optional { @_specialize(exported: true, where Wrapped == Int, S == [Int]) func foo<S : Sequence>(_ sequence: S) -> [Wrapped] { return Array(sequence) + (self.map { [$0] } ?? []) } }
🛠 1
Avatar
swiftbot BOT 25-Jun-18 05:29 AM
Author icon
koher
extension Optional { @_specialize(exported: true, where Wrapped == Int, S == [Int]) func foo<S : Sequence>(_ sequence: S) -> [Wrapped] { return Array(sequence) + (self.map { [$0] } ?? []) } }
Version:
swift-4.1.1-RELEASE
Output:
Error:
/usercode/main.swift:4:16: error: generic parameter 'S' could not be inferred return Array(sequence) + (self.map { [$0] } ?? []) ^
Avatar
omochimetaru 25-Jun-18 05:29 AM
やってみたけどだめだった
05:29
specializedの中だけで起きてる事ですね
Avatar
koher 25-Jun-18 05:30 AM
@_specialize(exported: true, where Wrapped == Int, S == [_]) みたいな記述を認めてほしいね。
05:32
この _ が他の構文の where でも書けるなら Parameterized Extension がなくても↓みたいなのもできるし。
extension Optional where Wrapped == _? { func flatten() -> Wrapped.Wrapped? { return flatMap { $0 } } }
05:33
@_specialize(exported: true, where Wrapped == Int, S == [Int]) で警告が出なくなるというのもいいけど、記述が冗長であることは否めない。 Int じゃなくて Foo<Bar<Baz>> とかだと 2 回書くのは大変。
Avatar
omochimetaru 25-Jun-18 05:34 AM
_ が書けると Higher Kind Type が書けるようになる気がする
Avatar
koher 25-Jun-18 05:38 AM
たしかに
05:41
protocol がジェネリックじゃないからギリギリ書けない?↓みたいなことが書きたいけど。
protocol Functor { associatedtype Value func map<F>(_ f: (Value) -> F.Value) -> F where F<_> == Self<_> }
Avatar
koher 25-Jun-18 06:55 AM
var foo: Foo? というプロパティを持つ型があって、そのメソッドで↓のようなことをやりたいときにうまい書き方ってありますか?
if self.foo == nil { // self.foo の初期化 self.foo = ... } let foo: Foo = self.foo! // 以下、foo を使うコード
Avatar
rintaro 25-Jun-18 07:05 AM
lazy var foo: Foo = ... にしない理由は何でしょう?
Avatar
koher 25-Jun-18 07:13 AM
↓みたいにメソッドの引数を使って初期化したいときとかですね。
class ViewController { var foo: Foo? = nil func bar(_ x: Int) { if self.foo == nil { // self.foo の初期化 self.foo = Foo(x) } let foo: Foo = self.foo! // 以下、foo を使うコード ... } }
Avatar
rintaro 25-Jun-18 07:14 AM
これぐらいしか思いつきませんでした😅
func bar(_ x: Int) { let foo = self.foo ?? (self.foo = Foo(x), self.foo!).1
(edited)
Avatar
koher 25-Jun-18 07:15 AM
よくこんなの思いつきますね😅
07:15
あ、でも ! が残ってる
Avatar
omochimetaru 25-Jun-18 07:16 AM
let foo: Foo = { guard let foo = self.foo else { let foo = ... self.foo = foo return foo } return foo }()
よくこれ書いてます
Avatar
koher 25-Jun-18 07:18 AM
なるほど・・・
Avatar
omochimetaru 25-Jun-18 07:18 AM
!はないけど self.foo が 2回出てくるので それが嫌だったら高階関数用意したほうが良いと思います
Avatar
rintaro 25-Jun-18 07:20 AM
extension Optional { mutating func ensure(default val: @autoclosure () -> Wrapped) -> Wrapped { if let v = self { return v } let v = val() self = v return v } } class C { var foo: Foo? func test(x: Int) { let foo = self.foo.ensure(default: Foo(x)) }
(edited)
Avatar
koher 25-Jun-18 07:21 AM
@omochimetaru こう?
func initUnwrap<T>(_ optional: inout T?, initialize: () -> T) -> T { if let value = optional { return value } let value = initialize() optional = value return value } let foo: Foo = initUnwrap(&self.foo) { Foo(x) }
Avatar
omochimetaru 25-Jun-18 07:21 AM
@koher そう
Avatar
koher 25-Jun-18 07:21 AM
あー、 inout より @rintaro さんの mutating func の方がキレイかな。
Avatar
omochimetaru 25-Jun-18 07:21 AM
りんたろさんの Optional の mutating func にするのはオシャレだな。
Avatar
koher 25-Jun-18 07:22 AM
mutating funcselfinout 引数を体現してる。
Avatar
omochimetaru 25-Jun-18 07:22 AM
第一引数の inout は mutatingメソッドと等価なわけだな
Avatar
koher 25-Jun-18 07:24 AM
この ensure 普通に標準ライブラリにほしい。
07:25
Booltoggle が通ったことを考えるとこれもいけるのでは?
Avatar
rintaro 25-Jun-18 07:26 AM
代入が返値を持つのを意識的に避けている気があるので、無理筋っぽい。
07:26
Bool.toggle は値返さないです。 (edited)
Avatar
koher 25-Jun-18 07:27 AM
Dictionarysubscript(_:default:) は同じじゃないですか?
Avatar
omochimetaru 25-Jun-18 07:27 AM
mutating func かつ return self な例が無いのか
07:27
Dictのsubscriptはなかった場合にdefaultが返るけどセットはしないんじゃないですっけ (edited)
Avatar
koher 25-Jun-18 07:28 AM
Bool.toggle は、メソッド単発の小さな改良のための Proposal の意でした。
07:29
Dictのsubscriptはなかった場合にdefaultが返るけどセットはしない
あれ?そっか。
Avatar
rintaro 25-Jun-18 07:50 AM
@swiftbot
extension Optional { @_specialize(exported: true, kind: partial, where S == [Int]) func foo<S : Sequence>(_ sequence: S) -> [Wrapped] where S.Element == Wrapped { return Array(sequence) + (self.map { [$0] } ?? []) } }
kind: partial だと警告消えますね。出力されるコードが同等なのかは調べてないです。
🛠 1
Avatar
swiftbot BOT 25-Jun-18 07:50 AM
Author icon
rintaro
extension Optional { @_specialize(exported: true, kind: partial, where S == [Int]) func foo<S : Sequence>(_ sequence: S) -> [Wrapped] where S.Element == Wrapped { return Array(sequence) + (self.map { [$0] } ?? []) } }
Version:
swift-4.1.1-RELEASE
Output:
Error:
Avatar
koher 25-Jun-18 08:26 AM
なるほど〜。でも本当に partial になっちゃってたら微妙ですね・・・。
Avatar
koher 25-Jun-18 08:39 AM
$cat full.swift extension Optional { @_specialize(exported: true, kind: full, where Wrapped == Int, S == [Int]) func foo<S : Sequence>(_ sequence: S) -> [Wrapped] where S.Element == Wrapped { return Array(sequence) + (self.map { [$0] } ?? []) } } let a: Int? = 7 let b: [Int] = [2, 3, 5] print(a.foo(b)) $cat partial.swift extension Optional { @_specialize(exported: true, kind: partial, where S == [Int]) func foo<S : Sequence>(_ sequence: S) -> [Wrapped] where S.Element == Wrapped { return Array(sequence) + (self.map { [$0] } ?? []) } } let a: Int? = 7 let b: [Int] = [2, 3, 5] print(a.foo(b)) $swift -O full.swift full.swift:2:60: warning: redundant same-type constraint 'Wrapped' == 'Int' @_specialize(exported: true, kind: full, where Wrapped == Int, S == [Int]) ^ full.swift:2:70: note: same-type constraint 'S.Element' == 'Int' implied here @_specialize(exported: true, kind: full, where Wrapped == Int, S == [Int]) ^ [2, 3, 5, 7] $swift -O partial.swift [2, 3, 5, 7] $md5 full MD5 (full) = 728efb9ffc6814bb17e0eedb72c5cda2 $md5 partial MD5 (partial) = c07fb4573afb1d8ae2ee53f30f341383
(edited)
08:39
とりあえず生成されたバイナリは違うみたいです。
08:41
(念のため同じファイルを 2 回コンパイルしたら同じ生成物ができました。)
Avatar
rintaro 25-Jun-18 08:48 AM
-module-name 揃えないと同じバイナリにならないので
08:48
$ swiftc -O partial.swift -module-name Test -o partial $ swiftc -O full.swift -module-name Test -o full
で試したら一致しました。
🙏 1
08:49
きちんと特殊化されているかはまた別問題ですが。
Avatar
koher 25-Jun-18 08:50 AM
なるほどー。
08:51
きちんと特殊化されているかはまた別問題ですが。
full の方で特殊化できてなかったらどの道これ以上やりようがないですし、仕方なさそうですね。
Avatar
ikesyo 25-Jun-18 11:07 AM
なんだか https://github.com/apple/swift/pull/13012 ちょうどこれっぽい話がされている
This PR adds a few items to the generics manifesto. The first two were discussed briefly on Twitter where @DougGregor requested a PR to add them. I plan to followup with a pitch to Swift evolutio...
11:07
generic associatestype
11:08
あくまでmanifestoへの追記のprですが
Avatar
koher 26-Jun-18 01:45 AM
↓こういうことでしょうか?🤔
protocol Functor { associatedtype Value associatedtype Transformed<T> func map<T>(_ transform: (Value) -> T) -> Transformed<T> } extension Optional { typealias Value = Wrapped typealias Transformed<T> = Optional<T> func map<T>(_ transform: (Wrapped) -> T) -> Optional<T> { ... } }
(edited)
Avatar
tarunon 26-Jun-18 01:46 AM
それ可能ならHigherKindedTypeそのものっぽい
Avatar
omochimetaru 26-Jun-18 01:46 AM
protocolのassociatedtypeに型パラメータを取るのか
Avatar
koher 26-Jun-18 01:46 AM
これって Functor の制約としては緩いですよね。
Avatar
tarunon 26-Jun-18 01:46 AM
assocの外側が自身じゃないとだめですかね
Avatar
koher 26-Jun-18 01:46 AM
ですねー。 (edited)
Avatar
tarunon 26-Jun-18 01:47 AM
でもやりたいことの8割はカバーできそう
Avatar
omochimetaru 26-Jun-18 01:47 AM
ああ、なるほど、Selfから剥がさないと意味ちがうか。
01:47
Optionalの場合に明示的に = Optional<T> と書いたから Functorになっただけで。
Avatar
koher 26-Jun-18 01:47 AM
Selfassociatedtype 含めて同一になっちゃうから強すぎて、
01:48
Functor とか Monad を作ろうとしたら Self から associatedtype を剥がしたものを記述できる構文が必要なはず。
01:51
↓の SelfProtocol みたいなものが必要。
protocol Functor { associatedtype Value func map<R: SelfProtocol>(_ transform: (Value) -> R.Value) -> R }
01:52
Protocol は変か。
01:52
OptionalProtocol じゃないもんな。
Avatar
tarunon 26-Jun-18 01:53 AM
Arrayもそうですね
01:53
ただsequenceになるだけならそれはfunctorではない
Avatar
koher 26-Jun-18 01:53 AM
type でもないし、なんと呼べばいいんだ?型クラス?
01:56
カインド = 「型の型」 - 例: Optional<Int> : * (型) - 例: Optional: * -> * (型→型)
01:56
Kind でよい?
01:57
↓とか?
protocol Functor { associatedtype Value func map<R: MyKind>(_ transform: (Value) -> R.Value) -> R }
Avatar
omochimetaru 30-Jun-18 07:22 AM
The review of SE-0217 — Introducing the !! "Unwrap or Die" operator to the Swift Standard Library begins now and runs through July 7, 2018. Reviews are an important part of the Swift evolution process. All review feedback should be either on this forum thread or, if you wo...
07:22
メッセージ付きの!!がレビュー入り
07:24
ここでも好評だったアイデアだけどラトナーは反対しとるね。
Avatar
koher 02-Jul-18 01:30 AM
While it addresses the issue of x!, it doesn't generalize or address the other failing forms in Swift, such as like try!, as!, array subscripting, integer overflows, etc.
なるほど。
01:31
まあ array subscripting とかはともかく(それが API の選択だから、それを利用している時点で意図が感じられる)、 try!as!optional! と同様の問題は抱えてるはずで、 !! じゃ不十分というのはその通りだ。 (edited)
Avatar
omochimetaru 02-Jul-18 02:18 AM
思ったより賛否両論の流れになってますねえ
Avatar
tarunon 02-Jul-18 02:19 AM
implicitly のある行に処理を差し込めるものを求めてるのかもしれない
02:20
try! foo.bar()! !! "失敗した理由"
02:20
こう書ける方が良いのかも?結構これは抜本的に変えないといけないからしんどいが (edited)
Avatar
rintaro 02-Jul-18 02:22 AM
Never as bottom type の流れに持っていけないかなー。
02:23
?? fatalError() でいければ問題ないわけだし。
Avatar
tarunon 02-Jul-18 02:23 AM
それはアリアリですね
02:23
try!やas!もtry?as? ?? fatalにすればok
Avatar
koher 02-Jul-18 02:25 AM
それ良さそうですね。
02:25
Never as bottom type ってなんで進まないんだろう?誰も Proposal 出さないから?実装の問題?
02:27
副作用があるメソッドの場合とかは微妙な気も。
try? foo.writeToFile(path) ?? fatalError("Reason")
Avatar
omochimetaru 02-Jul-18 02:38 AM
(Erica_Sadun) > Even if the team prefers to use a () -> Never rhs, I'd still recommend using !! over ?? to indicate the imbalance in roles between the safely unwrapped lhs and the unsafely unwrapped rhs. Expanding Never to be a bottom type does not fix this symbology mismatch. Whether Never is or is not a bottom type is orthogonal to this proposal. (edited)
02:40
Neverの話してるレスもあるけどEricaはそれでも !! が良いらしい。 Symbology mismatchが強調になってるんだけど、たしかに ?? でデフォルト値を与えると見せかけて fatalError で死ぬ っていうのも他の ! 用法と比べて危険性が見えにくい気もする。
Avatar
tarunon 02-Jul-18 10:25 AM
NeverがBottomになると嬉しいことが沢山あるのでそれはやった上で、T? ?? Neverだったらwarning出して!!使ってねと出るのがいいんじゃないかなぁとか (edited)
👀 1
Avatar
t.ae 05-Jul-18 01:14 AM
@swift-4.2.4
// https://github.com/apple/swift/blob/9286b3627d90523752cb1a2ffc02f7500ead0ea8/stdlib/public/core/FloatingPoint.swift.gyb#L2405-L2466 func test<T: BinaryFloatingPoint>(range: Range<T>) { print("\(T.self): \(range)") let delta = range.upperBound - range.lowerBound let maxSignificand = T.RawSignificand(1) << (T.significandBitCount + 1) // rand = generator.next(upperBound: maxSignificand) \in 0...maxSignificand-1 let zero: T.RawSignificand = 0 let maxx = maxSignificand - 1 let minimum = T(zero) * .ulpOfOne / 2 print("minimum == 0: \(minimum == 0)") let lb = delta * minimum + range.lowerBound print("lb == range.lowerBound: \(lb == range.lowerBound)") let maximum = T(maxx) * .ulpOfOne / 2 print("maximum < 1: \(maximum < 1)") let ub = delta * maximum + range.lowerBound print("ub < range.upperBound: \(ub < range.upperBound)") print("") } let floatRanges: [Range<Float>] = [1..<2, 2..<4] for range in floatRanges { test(range: range) } let doubleRanges: [Range<Double>] = [1..<2, 2..<4] for range in doubleRanges { test(range: range) }
Avatar
swift42 BOT 05-Jul-18 01:14 AM
Float: 1.0..<2.0 minimum == 0: true lb == range.lowerBound: true maximum < 1: true ub < range.upperBound: false Float: 2.0..<4.0 minimum == 0: true lb == range.lowerBound: true maximum < 1: true ub < range.upperBound: false Double: 1.0..<2.0 minimum == 0: true lb == range.lowerBound: true maximum < 1: true ub < range.upperBound: false Double: 2.0..<4.0 minimum == 0: true lb == range.lowerBound: true maximum < 1: true ub < range.upperBound: false
Avatar
t.ae 05-Jul-18 01:15 AM
↑これFloat.random(1..<2)で2が生成されうることの確認なんですがbugs.swift.orgに投げればいいんですかね
Avatar
t.ae 05-Jul-18 01:48 AM
https://bugs.swift.org/browse/SR-8152 そもそもテストカバレッジが十分でないみたい。 とりあえず投げときます。
Avatar
tarunon 05-Jul-18 01:50 AM
浮動小数点の問題で発生し得るのかしら
Avatar
t.ae 05-Jul-18 01:50 AM
みたいですね。
01:53
こんな面倒なコード書かなくても常にMaxを返すRNG作ってそれ渡せばいいですね。 RNG渡すことなんてそんな無いじゃんと思ってたけどテスタビリティは向上するのか。
Avatar
rintaro 05-Jul-18 02:01 AM
Float.random(in: Float(2.0) - .ulpOfOne ..< Float(2.0)) == Float(2.0)
で true 出てしまう。
Avatar
t.ae 05-Jul-18 02:02 AM
https://bugs.swift.org/browse/SR-8178 とりあえず投げました。
Avatar
t.ae 05-Jul-18 02:22 AM
@rintaro 修正ありがとうございます🙇
👍 1
Avatar
omochimetaru 05-Jul-18 05:20 AM
t.aeから直接話しを聞いたんだけど難しすぎワロタ
Avatar
koher 05-Jul-18 05:27 AM
@swift-4.2.4
let range = 0..<0 print(Int.random(in: range))
Avatar
swift42 BOT 05-Jul-18 05:27 AM
exit status: 4 with stderr:
Fatal error: Can't get random value with an empty range Current stack trace: 0 libswiftCore.so 0x00007f60e2191750 _swift_stdlib_reportFatalError + 168 1 libswiftCore.so 0x00007f60e1eec56a <unavailable> + 1488234 2 libswiftCore.so 0x00007f60e212859e <unavailable> + 3831198 3 libswiftCore.so 0x00007f60e1eec56a <unavailable> + 1488234 4 libswiftCore.so 0x00007f60e20838e9 <unavailable> + 3156201 5 libswiftCore.so 0x00007f60e1fb13d0 <unavailable> + 2294736 6 libswiftCore.so 0x00007f60e1fb1690 static FixedWidthInteger<>.random(in:) + 27 8 swift 0x0000000001041ffe <unavailable> + 12853246 9 swift 0x0000000001046122 <unavailable> + 12869922 10 swift 0x00000000004f82e2 <unavailable> + 1016546 11 swift 0x00000000004de86b <unavailable> + 911467 12 swift 0x00000000004d9ba0 <unavailable> + 891808 13 swift 0x000000000048a308 <unavailable> + 566024 14 libc.so.6 0x00007f60e52d3740 __libc_start_main + 240 15 swift 0x0000000000487fc9 <unavailable> + 557001 #0 0x0000000004106e24 PrintStackTraceSignalHandler(void*) (/usr/bin/swift+0x4106e24) #1 0x0000000004104cb2 llvm::sys::RunSignalHandlers() (/usr/bin/swift+0x4104cb2) #2 0x0000000004106fd2 SignalHandler(int) (/usr/bin/swift+0x4106fd2) #3 0x00007f60e6ba9390 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x11390) #4 0x00007f60e20838f1 $Ss18_fatalErrorMessage__4file4line5flagss5NeverOs12StaticStringV_A2HSus6UInt32VtFTf4nnddn_n (/usr/lib/swift/linux/libswiftCore.so+0x3028f1) #5 0x00007f60e1fb13d0 $Ss17FixedWidthIntegerPss08UnsignedC09MagnitudeRpzs06SignedC06StrideRpzrlE6random2in5usingxSnyxG_qd__zts21Random
Avatar
t.ae 05-Jul-18 05:27 AM
emptyかどうかはprecondition入ってます。
Avatar
koher 05-Jul-18 05:27 AM
なるほど。
Avatar
omochimetaru 05-Jul-18 05:27 AM
それは1行目で落ちてるのでは?
Avatar
koher 05-Jul-18 05:28 AM
0..<0 自体は OK (edited)
Avatar
omochimetaru 05-Jul-18 05:28 AM
そうか
05:28
Precondition・・・
Avatar
koher 05-Jul-18 05:28 AM
ClosedRange Closed でない Range の場合は Optional 返すでもいい気が。 (edited)
Avatar
t.ae 05-Jul-18 05:29 AM
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
05:30
いや内容的には違う話かな
Avatar
koher 05-Jul-18 05:32 AM
@swift-4.2.4
let range1 = 0..<1 print(String(describing: range1.first)) print(String(describing: Int.random(in: range1))) let range2 = 0..<0 print(String(describing: range2.first)) // print(String(describing: Int.random(in: range2))) // nil になってほしい
Avatar
swift42 BOT 05-Jul-18 05:32 AM
Optional(0) 0 nil
Avatar
koher 05-Jul-18 05:41 AM
まさにどうして range.random() じゃないのかが書いてあるね。でもいまいち英文の意味がわからない・・・。
05:44
"primary spelling" って何?一番よく使われる方法的な意味?
🤔 1
05:46
Also, since we decided pretty early on that we're going to trap if for whatever reason we can't get a random number
この trap って何を意味してる? signal を trap する話?それとも単にエラーハンドリング的な意味?
Avatar
t.ae 05-Jul-18 05:46 AM
エラーハンドリングでしょうねそこは (edited)
Avatar
rintaro 05-Jul-18 05:47 AM
RNG がランダムナンバーを生成出来ないなどの理由でエラーになるときは nil ではなく トラップして fatal なエラー (logic error) にすることを早い段階で決定した。 (edited)
🙏 1
05:49
というのと、 Collection.random() が空のときに nil を返すことも決定したので、 range.random() を正規の表現にすると、前述の non-nil のポリシーに例外を持たせる事になってしまう (edited)
Avatar
t.ae 05-Jul-18 05:51 AM
フォーラムの議論ちゃんと読んでないんですけどRNG自体にいろいろ生やす方針はなかったんですかね。
05:52
レス多すぎるし検索性も微妙なのでさっと探せない……
Avatar
omochimetaru 05-Jul-18 05:52 AM
当然話し合ってるんじゃないかな Randomスレむちゃくちゃ長いことめっちゃ伸びてたし
Avatar
koher 05-Jul-18 06:11 AM
なるほどー。
06:16
↓は O(n) なのかな? @swift-4.2.4
print(String(describing: "abcdefg".randomElement()))
Avatar
swift42 BOT 05-Jul-18 06:16 AM
Optional("b")
Avatar
t.ae 05-Jul-18 06:18 AM
collectionに生えてるならO(1)では?
Avatar
koher 05-Jul-18 06:19 AM
StringIndexInt じゃないので。
Avatar
omochimetaru 05-Jul-18 06:19 AM
CollectionはO(1)じゃないよ
Avatar
koher 05-Jul-18 06:19 AM
subscript は O(1) だけど
06:20
インデックスをランダムに選ぶためのインデックス列が O(1) で用意できないので
Avatar
koher 05-Jul-18 06:20 AM
count から最初にインデックスのインデックスを決めて、
06:21
順次アクセスかなと想像した。
Avatar
t.ae 05-Jul-18 06:21 AM
numericCastしてる
06:21
Complexity: O(1) if the collection conforms to RandomAccessCollection; otherwise, O(n), where n is the absolute value of n.
Avatar
t.ae 05-Jul-18 06:22 AM
なるほど
Avatar
rintaro 05-Jul-18 06:22 AM
.count も O(n) なので、なかなか重い処理だ。
Avatar
koher 05-Jul-18 06:23 AM
String って生成時に count も生成してるんじゃないのか・・・。
Avatar
rintaro 05-Jul-18 06:24 AM
ASCII 時の最適化などもあるので、一概には言えないですね。
Avatar
koher 05-Jul-18 06:25 AM
てっきりバイト列のチェックは走ってて、そのときにカウントだけは保持してるかなと思ってました。
06:27
RandomAccessCollection って subscript によるランダムアクセスが O(1) なんじゃなくて(当然これも満たされるけど)、インデックス間の任意個数分の移動が O(1) ってややこしいな・・・。
06:28
Collectionsubscript が O(1) は保証されてるんだっけ・・・。 String は O(1) として。
Avatar
omochimetaru 05-Jul-18 06:28 AM
Expected Performance Types that conform to Collection are expected to provide the startIndex and endIndex properties and subscript access to elements as O(1) operations.
Avatar
koher 05-Jul-18 06:28 AM
まさに同じとこ見てたw
06:30
O(n) は論外としても、 O(log n) は認めてほしい気も。
Avatar
omochimetaru 05-Jul-18 06:33 AM
StringGutsのGutsって結局なんなんだ(しばらく調べたけどわからず
Avatar
rintaro 05-Jul-18 06:34 AM
'guts' という言葉の意味自体は「内蔵」です。
Avatar
omochimetaru 05-Jul-18 06:34 AM
なるほど・・・
Avatar
t.ae 05-Jul-18 06:35 AM
内臓じゃなくて内蔵もあるんですか?
Avatar
omochimetaru 05-Jul-18 06:35 AM
Avatar
rintaro 05-Jul-18 06:35 AM
誤変換w 内臓です! (edited)
Avatar
t.ae 05-Jul-18 06:35 AM
ああ、誤変換でしたかw
Avatar
omochimetaru 05-Jul-18 06:35 AM
誤変換を無意識に再変換してたw
06:45
で、たしかにO(n)で文字をstartからendまでイテレートしてた。
😂 1
Avatar
rintaro 05-Jul-18 06:46 AM
ASCII でも CR+LF は 1 character なのが痛いところで 、O(n) ですね。
Avatar
omochimetaru 05-Jul-18 06:47 AM
マジすか
06:47
それは2文字でいいじゃんと思った。。
06:47
普通にSwiftで文字列を作ったらこのパスには行かなそうだな
06:50
あ、これはUTF8での要素数かな?
06:52
うーんそうか、どうせGraphemeCrusterの事考えると
06:52
Characterでのcountだけ持ってても特に意味がない気がする
06:53
count使うってことはおそらくそれとセットでCharacterでのindexも使うはずで、そこはどうせシーケンシャルに操作しないといかんし
06:54
文字数数えたいこととかはあるか。
06:54
Stringのソース、無限にバリエーションがあって広大
Avatar
koher 05-Jul-18 06:57 AM
文字数数えたいこととかはあるか。
むしろそれが count の一番の用途じゃないの?
Avatar
omochimetaru 14-Jul-18 01:49 PM
@t.ae 報告してたやつ直ってるけど、 upperboundにぶつかってたらもっかい呼び出すっていうワイルドなアプローチだった https://github.com/apple/swift/pull/17794/files
The problem seemed to come from the final addition + range.lowerBound.
Avatar
t.ae 14-Jul-18 01:49 PM
棄却して取り直せばOKってやつですね
Avatar
omochimetaru 14-Jul-18 01:50 PM
確率的に処理時間が伸びちゃうけどレアケースだから問題ないわな、っていって
13:50
mergeされてるけど
13:50
これって @t.ae が作ってたような
13:50
狂ったRNGのときに
13:50
無限ループしね?
Avatar
t.ae 14-Jul-18 01:50 PM
そこのテストケースについてもプルリクで話してましたね
Avatar
omochimetaru 14-Jul-18 01:51 PM
ん、どれだ
Avatar
t.ae 14-Jul-18 01:51 PM
コードレビューのどこかにあったはず
Avatar
omochimetaru 14-Jul-18 01:52 PM
ああインラインレビューか
Avatar
t.ae 14-Jul-18 01:52 PM
あれ?見つからないな……
13:52
ああふつうに最後にかいてあった
Avatar
omochimetaru 14-Jul-18 01:53 PM
Yeah, that is a concern, though it won't happen with non-pathological RNGs =) Maybe for the test use an RNG that instead generates [.min, .max, basic LCG sequence ...].
13:53
RNGとしてはナンセンスだから気にしなくていいって?
Avatar
t.ae 14-Jul-18 01:53 PM
そうですね。実際テストケースが詰まるので固定のシーケンスを生成するRNGもどきにしたということみたいです
Avatar
omochimetaru 14-Jul-18 01:53 PM
う〜〜〜〜〜〜〜〜ん・・・・・・・・・・
13:54
プラクティカルだ・・・
13:54
乱数モジュールの事考えてるときは数理的な発想になるから違和感あるけどまあそうか・・・
Avatar
t.ae 14-Jul-18 01:55 PM
内部的に複数回乱数引くことがあるので100回max生成してその後はランダム〜みたいなのが良いようにも思えますね
Avatar
norio_nomura 14-Jul-18 08:04 PM
Never as bottom になったの? https://twitter.com/mdiep/status/1018159704818831360
SE-0215, Conform Never to Equatable and Hashable, has been accepted! 🎉 https://t.co/zBneV1oWiZ The core team also concluded: 1. Never should also conform to Error and Comparable 2. Never should become a blessed bottom type Exactly the resolution I hope...
Avatar
koher 15-Jul-18 03:18 AM
お、bottomになったならうれしいですね!
Avatar
t.ae 17-Jul-18 12:43 AM
↑絡みかunwrap or dieがrejectされましたね https://forums.swift.org/t/se-0217-the-unwrap-or-die-operator/14107/222
Proposal rejected The core team has decided to reject this proposal as written. However, the core team concurs that the motivating problems posed by the proposal are important to solve, as did an overwhelming majority of commenters who participated in the public review. The f...
Avatar
koher 17-Jul-18 01:59 AM
言及されてますね。
Meanwhile, elsewhere in swift-evolution, the core team has also accepted SE-0215 — Conform Never to Equatable and Hashable 9, and came out of that discussion strongly in favor of investigating making Never be a subtype of every other type. This requires its own design cycle, but it fills in a general gap in the type system, and would enable the idiom x ?? fatalError("message") without any additions to the standard library.
Avatar
koher 25-Jul-18 06:04 AM
↓の方法、 Base が値型だとオーバーヘッド大きそう。
struct Extension<Base> { let base: Base init (_ base: Base) { self.base = base } } protocol ExtensionCompatible { associatedtype Compatible static var ex: Extension<Compatible>.Type { get } var ex: Extension<Compatible> { get } } extension ExtensionCompatible { static var ex: Extension<Self>.Type { return Extension<Self>.self } var ex: Extension<Self> { return Extension(self) } }
https://qiita.com/motokiee/items/e8f07c11b88d692b2cc5
## Extensionをモダンでオシャレにしたい この記事の結論を先に書いておくと、
UIColor.yamabuki
のように書いているExtensionを以下のようにオシャレに書くことができる、と...
06:04
↓ここで毎回コピーが走る。
var ex: Extension<Self> { return Extension(self) }
Avatar
Kishikawa Katsumi 25-Jul-18 06:07 AM
気にするようなオーバーヘッドあるかな。まあ使い方によるわけですけれど。
Avatar
omochimetaru 25-Jul-18 06:07 AM
これってまさにこの前の read property を使えば
06:07
コピーを回避できるパターンじゃないかしら
06:11
いや、無理か・・・
Avatar
tarunon 25-Jul-18 06:11 AM
これ値型でやろうとすると結構大変になる
06:11
そもそもfoo.exを生やすだけで大変
Avatar
koher 25-Jul-18 06:11 AM
@Kishikawa Katsumi もしプロパティが 10 個あってそれぞれ 8 バイトだとしたら、 foo.ex.bar ってやるだけで 80 バイトのコピーが走るってことですよね?
06:13
@tarunon 拡張の仕方自体に値型で大変な点ありますっけ? set しようとしたら大変ですが。
Avatar
Kishikawa Katsumi 25-Jul-18 06:13 AM
特に気にするようなオーバーヘッドじゃないと思いますね。私が普段書いてるプログラムでは。
Avatar
tarunon 25-Jul-18 06:14 AM
classでこれやるのって現実的にはBaseClass一括になるんですが
06:14
値型だとそうはいかないので一個ずつ定義する必要が出てきてあんまり嬉しくないになりがちな感じです
06:15
extension Foo: ExCompatibleを必要な全てのstructに一つずつ書いていくことに
Avatar
koher 25-Jul-18 06:15 AM
@Kishikawa Katsumi ボタン一回押したらそれが数回呼ばれるとかだと問題にならないですね。リアルタイム性が重要なアプリで、ループの中で呼ぶとかだと辛そうです。
Avatar
Kishikawa Katsumi 25-Jul-18 06:15 AM
そういうことはあると思います。
Avatar
omochimetaru 25-Jul-18 06:16 AM
extension Foo: ExCompatibleを必要な全てのstructに一つずつ書いていくことに
それが大変とは思わなかったw
06:16
ようするに対応する事を型ごとに表明するだけだよね、必然的なコストでは・・・?
Avatar
koher 25-Jul-18 06:16 AM
@tarunon Conditional Conformance でどうにかできたりしないですか?(コード書いてないので自信ないですが・・・) (edited)
Avatar
omochimetaru 25-Jul-18 06:16 AM
@koher Conditionalに書けるってことは、そのConditionの起点になるProtocolへのconformanceは結局必要になるはずなので、手数が同じに思います
Avatar
koher 25-Jul-18 06:17 AM
@omochimetaru@tarunon さんが話してるのは BaseClass があるパターンなので、値型に対してもバラバラに記述しないといけないケースをプロトコルでどうにかならないかなと。
Avatar
tarunon 25-Jul-18 06:17 AM
ならないっす
Avatar
Kishikawa Katsumi 25-Jul-18 06:18 AM
ただ、基本的にこういう類のパフォーマンスがどれだけ影響するかは自明ではないし、優先度としては一般的に高くないはずです。
Avatar
tarunon 25-Jul-18 06:18 AM
IntX UIntX String StaticString ... と書いてるとウーンって感じになるし流石に用途ごとに全部やるのは
Avatar
omochimetaru 25-Jul-18 06:19 AM
@koher @tarunon BaseClassを指定するのと、Foo: ExComaptible するのと、 共通のProtocolを置くのって、どれも同じことじゃないですか?
Avatar
koher 25-Jul-18 06:20 AM
extension メソッドの実装じゃなくて、 conform の話をしてるのか。
Avatar
omochimetaru 25-Jul-18 06:20 AM
実際のexntensionする内容に関しては、 全く異なる型ならそもそも拡張で提供できる機能も全く異なるはずだし
06:20
そこに共通性があるならその共通性はProtocolで、拡張する前に宣言できるはずなので
06:21
特に値型ゆえに面倒になっている理由になっていないように聞こえます。
Avatar
tarunon 25-Jul-18 06:22 AM
protocolのベースを後付けで増やせないから、classの時のやり方とは違う方法を考えた方が良い、が正しそう
Avatar
omochimetaru 25-Jul-18 06:23 AM
protocol P0 で使える .ex.<hogehoge for P0> と protocol P1 で使える .ex.<fugafuga for P1> が
06:24
struct STone: P0, P1 {} の場合に両方使えるようにするのがむずい、みたいな事? (edited)
06:25
それは大丈夫そうだな。
extension Reactive where Base : P0 { ... } extension Reactive where Base : P1 { ... }
Avatar
lovee 25-Jul-18 07:35 AM
パフォーマンスについてはこちらの記事に書いてありますね: https://tech.starttoday-tech.com/entry/swift_modern_extensions まあそれほど気にするようなオーバーヘッドはないかと思います;NotAutoLayoutもこれ大量に使ってますがそれでもAuto Layout使わないライブラリーの中でも最速ですし() https://github.com/layoutBox/LayoutFrameworkBenchmark
VASILYのiOSエンジニアにこらすです。最近、Swift Evolutionに私の2つ目の提案がマージされました。 今回は、Swiftで型にExtensionを作る特殊な方法について説明します。 今回紹介する方法を使ってExtensionを作ると...
LayoutFrameworkBenchmark - Benchmark the performances of various Swift layout frameworks (autolayout, UIStackView, PinLayout, LayoutKit, FlexLayout, Yoga, ...)
👍 1
Avatar
omochimetaru 25-Jul-18 09:31 AM
レイアウトライブラリの内部だと、オブジェクトの数やループする数が、たかだか画面コンポーネントの数なので、影響は感じ無さそうです
Avatar
koher 25-Jul-18 09:37 AM
僕が作っている Image 型とかで、ピクセル単位でループしてたりするとちょっと許容できなさそうですね。 (edited)
09:38
あと、↑のリンク先の Example<Base>class になってますが、これは struct でないとパフォーマンス的によりまずい気がします(ヒープに確保されるので)。 (edited)
09:44
こっちでもベンチマークとってみたら、参照型でも ex. だとずいぶん遅くなって謎・・・。何か間違ってんのかなぁ。
09:45
あと、 : ExtensionConvertible するだけだと -c release でも ex が特殊化されてないみたいで、 ex_ に比べて数十倍遅くなってしまった・・・。
09:46
あえて個々の extensionex の実装を書き下すと(おそらく) Extension が特殊化されて数倍の遅さ程度になった。
09:50
色々謎だけどとりあえずリポジトリ公開しました。 https://github.com/koher/ExPerformance
Contribute to ExPerformance development by creating an account on GitHub.
09:51
FoostructBarclass
09:51
テストで measure してるので
swift test -c release
で実行。
Avatar
tarunon 25-Jul-18 09:58 AM
Generics、関数はSpecializeされるけど型はSpecializeされない、、ですよね?
09:58
もうされるようになった?
09:58
だからEx<T>はどうやってもオーバーヘッド出ると思います
09:59
無視できるかはさておき
Avatar
omochimetaru 25-Jul-18 10:02 AM
型っていうかストレージはされないっぽいね
Avatar
norio_nomura 25-Jul-18 10:28 AM
Swift 4.2で@inlinableとか使うとtestFooDirecttestFooExampleは同等になった。
public struct Example<Base> { @usableFromInline let base: Base @inlinable public init(_ base: Base) { self.base = base } } public protocol ExampleCompatible { associatedtype CompatibleType var ex: CompatibleType { get } } extension ExampleCompatible { @inlinable public var ex: Example<Self> { return Example(self) } }
extension Foo { @inlinable public var ex_ab: Int { return a + b } } extension Example where Base == Foo { @inlinable public var ab: Int { return base.a + base.b } }
(edited)
10:30
testBarExample@inlinableを色々つけてもtestBarDirectより10倍くらい遅い。
Avatar
rintaro 25-Jul-18 10:32 AM
https://github.com/apple/swift/blob/e9cb62d4/stdlib/public/SwiftOnoneSupport/SwiftOnoneSupport.swift#L159-L173 型が specialize されないっていうのと、これの関係が気になる。
swift - The Swift Programming Language
Avatar
norio_nomura 25-Jul-18 10:39 AM
ああ、public final class BarにしたらtestBarExampletestBarDirectも同等になった。 (edited)
Avatar
norio_nomura 25-Jul-18 10:48 AM
@_specializeでspecialize実装を生成しておくよりも@inlinableを活用すべき、という理解で合ってるのかな?
Avatar
tarunon 25-Jul-18 01:30 PM
私の理解が正しければinline化とspecializeはゴールが違っていてこの場合は特別な例で近いゴールになってるだけ、な気がする
13:34
あー、、、仮にEx<T>に生えたメソッド群がインライン化可能なら、オーバーヘッドを無くせる可能性が出てきますね
Avatar
norio_nomura 26-Jul-18 12:21 AM
少し試した限りでは@inlinableはかなり有効ですね。
Avatar
koher 26-Jul-18 02:17 AM
final でないクラスで遅くなるのは、 ex の呼び出しと ex の持つ self 経由での呼び出しとで 2 回動的ディスパッチが走るからでしょうか?で、 final にすると両方静的ディスパッチになるので速くなる。 (edited)
Avatar
tarunon 26-Jul-18 02:18 AM
Ex<T>のTに制約かけて何かやってるとそこが動的になるはず
02:19
exそのものの呼び出しは動的にならない気がする、直感的には
Avatar
koher 26-Jul-18 02:19 AM
Barfinal でなかったら、 bar.ex が動的ですよね。
02:19
exself を呼び出すところは特殊化できないなら動的になって、
02:20
さらに self.ab するところが動的か静的か。
Avatar
tarunon 26-Jul-18 02:20 AM
どういう記述になってるかによりそうですが
02:21
そもそもextensionに記述したものはoverrideできない(3まではできた)なので
02:21
少し違う気がしています
Avatar
koher 26-Jul-18 02:21 AM
let bar = Bar() var sum = 0 for _ in 0..<N { sum += bar.ex.ab }
Avatar
tarunon 26-Jul-18 02:21 AM
静的に型検査されたEx<Base>になるはず
02:21
コンパイル時の型のExになる
02:21
少なくともRxSwiftはそうです
Avatar
koher 26-Jul-18 02:22 AM
あー、 abExtension だからオーバーライドできないことが保証されて静的になるってことですね。
Avatar
tarunon 26-Jul-18 02:22 AM
そう
Avatar
koher 26-Jul-18 02:23 AM
そうすると、↑の final 付けるかどうかの差は、 ex 関係なくて単に bar.ex が動的/静的ディスパッチになっているかの差?
02:23
それなら、 bar.ex_ab のときも速くなりそう。 (edited)
Avatar
norio_nomura 26-Jul-18 02:24 AM
静的になる != inline化される、では無いと思う。実際、
extension Example where Base == Bar { @inlinable public var ab: Int { return base.a + base.b } }
@inlinable有無で速度が違うし。
Avatar
tarunon 26-Jul-18 02:25 AM
こっちはinline化された結果、exの存在が無かったことになると思っていて
Avatar
koher 26-Jul-18 02:25 AM
そのインライン化ってコンパイラが勝手に最適化してくれるイメージだったんですが、 @inlineable がないとインライン化されないんでしょうか?
Avatar
tarunon 26-Jul-18 02:25 AM
その最適化が可能ならオーバーヘッドがほぼ無くなりそうだなと
02:25
インライン化は明示しないと基本やってくれないと思います
Avatar
norio_nomura 26-Jul-18 02:25 AM
モジュール内で使う限りは勝手にインライン化されるんじゃ無いかな?
Avatar
koher 26-Jul-18 02:26 AM
あー、今モジュールを超えてるからか。
Avatar
tarunon 26-Jul-18 02:26 AM
モジュールの内外で違う
02:26
のか
Avatar
omochimetaru 26-Jul-18 02:26 AM
@inlineable はモジュールをまたいでインライン化可能できるようにする指定子
02:26
これを指定するとコンパイル後のバイナリにASTが埋め込まれる
02:26
そうしないとインライン化できないから。
Avatar
koher 26-Jul-18 02:26 AM
確かに呼び出しはテスト側だからモジュールまたいでた。
Avatar
omochimetaru 26-Jul-18 02:26 AM
デメリットとしてバイナリサイズが肥大する。
Avatar
norio_nomura 26-Jul-18 02:26 AM
ExPerformanceでは別モジュールのExPerformanceTestsで使ってるから。
Avatar
tarunon 26-Jul-18 02:27 AM
でもまあ現実的に計測するならモジュールまたぎの方が
Avatar
rintaro 26-Jul-18 02:27 AM
コンパイル後のバイナリにASTが埋め込まれる
僕の理解では swiftmodule に SIL 実装が埋め込まれる です。
👍 1
Avatar
tarunon 26-Jul-18 02:27 AM
実態に近いですよね
Avatar
koher 26-Jul-18 02:27 AM
@tarunon
その最適化が可能ならオーバーヘッドがほぼ無くなりそうだなと
インライン化できたとしても、 Example<T>self への代入によるコピーコストまでなかったことにはならない気がするんですよねぇ。
Avatar
omochimetaru 26-Jul-18 02:27 AM
SILか。(ちゃんと確認してないです) (edited)
Avatar
tarunon 26-Jul-18 02:28 AM
Exの参照なければ生成しない、までアグレッシブにできない、できないか
02:29
副作用無しを保証する指定子みたいなのが出てくると、できることが増えそう
Avatar
koher 26-Jul-18 02:32 AM
↓の二段を解釈してコピーを省略するのはハードルが高そう・・・。
extension Foo: ExampleCompatible { public var ex: Example<Foo> { return Example(self) } } extension Example where Base == Foo { public var ab: Int { return base.a + base.b } }
02:33
同じ領域参照するにしても、 Example<T> が値を保持してるのを参照にしなきゃいけないし。 @nonescaping 的な、即時解放されることが保証されてればコピー省略できるのかなぁ。
Avatar
omochimetaru 26-Jul-18 02:33 AM
LLVM-IRを見てみるのが良いのでは モジュール跨ぎの状況を生コマンドで構築するのはちょっと大変だけど
Avatar
norio_nomura 26-Jul-18 02:35 AM
とりあえず、@inlinablefinalを活用してのExPerformanceTestsのmeasuredはこんな感じ。
…testBarDirect]' measured [Time, seconds] average: 0.009, … …testBarExample]' measured [Time, seconds] average: 0.010, … …testFooDirect]' measured [Time, seconds] average: 0.004, … …testFooExample]' measured [Time, seconds] average: 0.004, …
(edited)
02:37
活用前:
…testBarDirect]' measured [Time, seconds] average: 0.018, … …testBarExample]' measured [Time, seconds] average: 0.614, … …testFooDirect]' measured [Time, seconds] average: 0.024, … …testFooExample]' measured [Time, seconds] average: 0.767, …
Avatar
koher 26-Jul-18 02:37 AM
なんでコピーコストがないんだろう。無視できるほど小さいのかなぁ。 80 バイトあるんだけどなぁ。
02:38
ジェネリック型変数が特殊化されないとすると、 existential みたいにある程度以上大きな値は COW バッファーになってる?
02:43
bot で -emit-ir できるんだっけ? @swiftbot -O -emit-ir
(edited)
🛠 1
Avatar
swiftbot BOT 26-Jul-18 02:43 AM
(edited)
Author icon
koher
let N = 10_000_000 public struct Example<Base> { let base: Base public init(_ base: Base) { self.base = base } } public protocol ExampleCompatible { associatedtype CompatibleType var ex: CompatibleType { get } } extension ExampleCompatible { public var ex: Example<Self> { return Example(self) } } public struct Foo { public var a: Int = 1 public var b: Int = 2 public var c: Int = 3 public var d: Int = 4 public var e: Int = 5 public var f: Int = 6 public var g: Int = 7 public var h: Int = 8 public var i: Int = 9 public var j: Int = 10 public init() {} } extension Foo { public var ex_ab: Int { return a + b } } extension Foo: ExampleCompatible { public var ex: Example<Foo> { return Example(self) } } extension Example where Base == Foo { public var ab: Int { return base.a + base.b } } let foo = Foo() var sum = 0 for _ in 0..<N { sum += foo.ex.ab } print(foo)
Version:
swift-4.1.1-RELEASE
Output:
Foo(a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9, j: 10)
Error:
Avatar
omochimetaru 26-Jul-18 02:45 AM
#swift に例があります
Avatar
koher 26-Jul-18 02:46 AM
@swift-4.1.3 -O -emit-ir
let N = 10_000_000 public struct Example<Base> { let base: Base public init(_ base: Base) { self.base = base } } public protocol ExampleCompatible { associatedtype CompatibleType var ex: CompatibleType { get } } extension ExampleCompatible { public var ex: Example<Self> { return Example(self) } } public struct Foo { public var a: Int = 1 public var b: Int = 2 public var c: Int = 3 public var d: Int = 4 public var e: Int = 5 public var f: Int = 6 public var g: Int = 7 public var h: Int = 8 public var i: Int = 9 public var j: Int = 10 public init() {} } extension Foo { public var ex_ab: Int { return a + b } } extension Foo: ExampleCompatible { public var ex: Example<Foo> { return Example(self) } } extension Example where Base == Foo { public var ab: Int { return base.a + base.b } } let foo = Foo() var sum = 0 for _ in 0..<N { sum += foo.ex.ab } print(foo)
Avatar
swift41 BOT 26-Jul-18 02:46 AM
exit status: 1 with stderr:
<unknown>:0: error: option '-emit-ir' is not supported by 'swift'; did you mean to use 'swiftc'?
Avatar
norio_nomura 26-Jul-18 02:48 AM
swiftcではなくswiftなので、-Xfrontend -emit-irを使ってください。 (edited)
🙏 1
Avatar
lovee 26-Jul-18 03:14 AM
@omochimetaru
レイアウトライブラリの内部だと、オブジェクトの数やループする数が、たかだか画面コンポーネントの数なので、影響は感じ無さそうです
NotAutoLayout内部の話になると、nal の度にインスタンス作ってるだけでなく、何かを設定するときも大量にインスタンス作ってます、例えばサンプルコード出してみると
self.nal.layout(self.viewA) { $0 .setTopCenter(by: { $0.topCenter }) .setWidth(by: { $0.width }) .fitHeight() }
上記画面コンポーネントは viewA だけだけど、作ったインスタンスは nal $0 .setTopCenter $0.topCenter setWidth $0.width .fitHeight の7つあります
Avatar
omochimetaru 26-Jul-18 03:16 AM
@lovee viewAに対してたかだか10倍程度ですよね、 僕がイメージしてる「たくさん」は、 ゲームコンテンツなどでワールドに3Dオブジェクトが500個程度描画されていて、 それぞれの姿勢行列 Matrix4x4 に対して、 回転制御を行うためのクォータニオン変換などの計算ユーティリティが、 このextensionで書かれていたら、みたいなオーダーです。 これを毎フレームの16ms以内に完了しないといけない。 (edited)
Avatar
lovee 26-Jul-18 03:17 AM
そこまでいくと「たくさん」の定義は違って来ますね 😇
Avatar
omochimetaru 26-Jul-18 03:17 AM
このときに、 Reactive(base: self) で Base == Matrix4x4 なら 32bit floatが16個になるので
03:17
コピーコストも大きそうです。
Avatar
lovee 26-Jul-18 03:19 AM
classでMatrix4x4を包むしかなさそう 🤔
Avatar
omochimetaru 26-Jul-18 03:20 AM
.ex形式にしないで 直接extensionを書けば良いと思います。 まあ、今の会話の流れだと、それでもinline化によってコピーが回避されてる説が出てきましたが。
Avatar
lovee 26-Jul-18 03:22 AM
試してみたいですねinline化
Avatar
omochimetaru 26-Jul-18 03:22 AM
今ちょっと忙しいので後でIR見てみようと思ってます
Avatar
lovee 26-Jul-18 03:24 AM
:sasuga:
Avatar
koher 26-Jul-18 03:42 AM
@swift-4.1.3 -O -Xfrontend -emit-ir
let N = 10_000_000 public struct Example<Base> { let base: Base public init(_ base: Base) { self.base = base } } public protocol ExampleCompatible { associatedtype CompatibleType var ex: CompatibleType { get } } extension ExampleCompatible { public var ex: Example<Self> { return Example(self) } } public struct Foo { public var a: Int = 1 public var b: Int = 2 public var c: Int = 3 public var d: Int = 4 public var e: Int = 5 public var f: Int = 6 public var g: Int = 7 public var h: Int = 8 public var i: Int = 9 public var j: Int = 10 public init() {} } extension Foo { public var ex_ab: Int { return a + b } } extension Foo: ExampleCompatible { public var ex: Example<Foo> { return Example(self) } } extension Example where Base == Foo { public var ab: Int { return base.a + base.b } } let foo = Foo() var sum = 0 for _ in 0..<N { sum += foo.ex.ab } print(foo)
Avatar
swift41 BOT 26-Jul-18 03:42 AM
; ModuleID = '-' source_filename = "-" target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" %TSi = type <{ i64 }> %T4main3FooV = type <{ %TSi, %TSi, %TSi, %TSi, %TSi, %TSi, %TSi, %TSi, %TSi, %TSi }> %swift.type = type { i64 } %swift.protocol = type { i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i32, i32, i16, i16, i32 } %swift.refcounted = type { %swift.type*, i64 } %swift.full_boxmetadata = type { void (%swift.refcounted*)*, i8**, %swift.type, i32, i8* } %swift.opaque = type opaque %swift.type_pattern = type opaque %swift.protocol_requirement = type { i32, i32 } %swift.protocol_conformance = type { i32, i32, i32, i32 } %swift.type_metadata_record = type { i32, i32 } %Ts27_ContiguousArrayStorageBaseC = type <{ %swift.refcounted, %Ts10_ArrayBodyV }> %Ts10_ArrayBodyV = type <{ %TSC22_SwiftArrayBodyStorageV }> %TSC22_SwiftArrayBodyStorageV = type <{ %TSi, %TSu }> %TSu = type <{ i64 }> %T4main7ExampleV = type <{}> %T4main7ExampleV.2 = type <{}> %T4main7ExampleVyAA3FooVG = type <{ %T4main3FooV }> @_T04main1NSivp = hidden local_unnamed_addr global %TSi zeroinitializer, align 8 @_T04main3fooAA3FooVvp = hidden local_unnamed_addr global %T4main3FooV zeroinitializer, align 16 @_T04main3sumSivp = hidden local_unnamed_addr global %TSi zeroinitializer, align 8 @_T0s23_ContiguousArrayStorageCyypGML = linkonce_odr hidden local_unnamed_addr global %swift.type* null, align 8 @_T0ypML = linkonce_odr hidden local_unnamed_addr global %swift.type* null, align 8 @_swift_getExistentialTypeMetadata = external local_unnamed_addr global %swift.type* (i1, %swift.type*, i64, %swift.protocol**)* @_swift_allocObject = external local_unnamed_addr global %swift.refcounted* (%swift.type*, i64, i64)* @_T0s27_ContiguousArrayStorageBaseC16countAndCapacitys01_B4BodyVvpWvd = external local_unnamed_addr global i64, align 8 @0 = private constant [11 x i8] c"4main3FooV\00", section "swift3_typeref" @"\01l__swift3_reflection_descriptor" = private constan
Avatar
koher 26-Jul-18 03:43 AM
なんか手元でやったのと結果が違うと思ったら Linux だからか。
Avatar
koher 26-Jul-18 04:01 AM
$ swift demangle S4main7ExampleVA2A3FooVRszlE2abSivg $S4main7ExampleVA2A3FooVRszlE2abSivg ---> (extension in main):main.Example<A where A == main.Foo>.ab.getter : Swift.Int
04:05
swiftc -O -emit-ir main.swift | grep S4main7ExampleVA2A3FooVRszlE2abSivg するととんでもなく長い行が出てくる😭
Avatar
omochimetaru 27-Jul-18 05:02 AM
Enables local refactoring on a class declaration to generate member wise initializer Resolves SR-7292.
05:02
これXcode10で使えると良いな
Avatar
rintaro 27-Jul-18 05:03 AM
4.2 に今から入れるのは無理だと思います。残念。
😣 1
Avatar
koher 27-Jul-18 05:06 AM
@rintaro もしかして↓も 4.2 に入らないんでしょうか? https://github.com/apple/swift-evolution/blob/master/proposals/0216-dynamic-callable.md
swift-evolution - This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
05:06
SE-0195 だけ入って SE-0216 は入らないとか辛い気が・・・。
Avatar
rintaro 27-Jul-18 05:08 AM
https://swift.org/blog/4-2-release-process/ によると、April 20 の final branching 以降は
After the final branch date there will be a “bake” period in which only select, critical fixes will go into the release (via pull requests).
This post describes the goals, release process, and estimated schedule for Swift 4.2.
🙏 1
Avatar
koher 27-Jul-18 05:09 AM
なるほど。 SE-0216 は Chris Lattner 肝いりだし、 Swift for TensorFlow との兼ね合いでも早く入れたいだろうし、入ると期待したいですね・・・。
05:10
まだマージもされてないですが・・・。
Avatar
tarunon 02-Aug-18 06:36 AM
struct Foo { init?(...) } これの時に、左辺の型がFoo?の場合に右辺を.initで型省略できないの、仕方ないとは理解しつつも感情が受け付けない
Avatar
omochimetaru 02-Aug-18 06:37 AM
それ不便だよね
Avatar
vicktorManuel 05-Aug-18 03:42 PM
you can only public struct Foo { public var j: Int ! ............... --------- }
Avatar
rintaro 09-Aug-18 07:15 AM
https://github.com/apple/swift/pull/18579 これは嬉しい!インターフェイスでデフォルト値が default じゃなくてきちんと表示されるようになります。
This allows us to dump it in the generated interface, though it's still not syntax-highlighted. This is necessary for textual module interfaces, but it's also just a longstanding request fo...
❤ 1
Avatar
omochimetaru 09-Aug-18 07:16 AM
おお
07:22
diff眺めたのですけど、
struct StoredDefaultArgument { Expr *DefaultArg = nullptr; Initializer *InitContext = nullptr; StringRef StringRepresentation; };
Avatar
tarunon 09-Aug-18 07:23 AM
nilとか参照先のフィールドも出るようになる感じでしょうか
Avatar
omochimetaru 09-Aug-18 07:23 AM
基本これだけですか?
07:23
Parse/ParsePattern.cppでもソースレンジを渡してるだけだから、本当にそのまま・・・
Avatar
Kishikawa Katsumi 09-Aug-18 07:24 AM
これはとても嬉しいですね。
Avatar
rintaro 09-Aug-18 07:25 AM
Swift4あたりから、デフォルト引数の中でプライベートな値が使えなくなったので、単純なソーステキストのコピーで問題ないという判断でしょうね。
Avatar
omochimetaru 09-Aug-18 07:27 AM
なるほど?なんか変なことになるケースが無いか考えてるんですけど思いつかないし大丈夫なのか。 たしかにプライベートコンテキストだった時代だと変な事にもなるけど・・・
Avatar
Kuniwak 09-Aug-18 08:28 AM
#swift-zatsu で話してた件ですが、capture で別名つける方法がいけるか?と思ってやったら予想外の結果に。
class Example { func test() { let f = { [weak weakSelf = self] in guard let `self` = weakSelf else { return } // Set a breakpoint at here print(self) } f() } } Example().test()
今度は謎の結果に…
(lldb) po self error: <EXPR>:3:1: error: use of unresolved identifier 'self' self ^~~~ (lldb) fr var (@lvalue example.Example?) weakSelf = 0x00000001009002b0 (example.Example) self = 0x00000001009002b0 {}
08:32
とりあえず、self という名前での変数宣言をやめましょうということですね…
08:32
昔採用していた guard let this = self else { return } は案外賢かったのかもしれない… (edited)
Avatar
koher 09-Aug-18 08:39 AM
( Swift の話が 4 本並行してしまった・・・。)
08:39
僕は zelf 派ですが、あまり zelf の人いないですね・・・。
Avatar
omochimetaru 09-Aug-18 08:39 AM
僕は wselfsselfuself (edited)
Avatar
Kishikawa Katsumi 09-Aug-18 08:39 AM
私はthis/me/self/stringSelfその他どれも微妙だと思っていて、
👀 1
08:39
pageControl.rx.controlEvent(.valueChanged) .subscribe(onNext: { [weak self] in guard let currentPage = self?.pageControl.currentPage else { return } guard let contentOffset = self?.scrollView.contentOffset else { return } guard let currentIndex = self?.currentIndex else { return } ...
😃 1
Avatar
koher 09-Aug-18 08:39 AM
みんなばらばら😭
Avatar
Kishikawa Katsumi 09-Aug-18 08:40 AM
^ みたいにselfの先の必要なプロパティを個別にguardでとることが多いですね。
Avatar
Kuniwak 09-Aug-18 08:40 AM
これ、本質的な問題は LLDB でやりづらいってだけなので、LLDB 直す方向でいきたいですね…
Avatar
Kishikawa Katsumi 09-Aug-18 08:40 AM
ちなみにこれはだいぶ極端な例。
Avatar
Kuniwak 09-Aug-18 08:40 AM
そうすれば、 self 派も weakSelf capture 派も救われる…
Avatar
omochimetaru 09-Aug-18 08:41 AM
@Kuniwak 僕が self の再定義をしないのは、デバッグは関係なくて、
08:41
self に再定義したそのスコープでさらにクロージャーを作るときに
Avatar
koher 09-Aug-18 08:41 AM
@Kishikawa Katsumi self?. 方式だと、 self によらない処理が書かれていると self が解放されていてもそれが走ってしまいませんか?
Avatar
omochimetaru 09-Aug-18 08:41 AM
[weak self] を書き忘れた場合などで、 self が強なのか弱なのかゴチャゴチャしてくるからです
08:42
正しくは、弱でキャプチャして、冒頭で強にリバインドですが、 「弱でキャプチャして冒頭で強にリバインド」を、まるまる忘れちゃって、そのまま強でキャプチャするミスが
08:42
見た目にわかりづらいと思っています
Avatar
Kuniwak 09-Aug-18 08:42 AM
@omochimetaru うーん、なるほど…?個人的には capture で別名を基本として Lint で検査が健全な感じします
Avatar
omochimetaru 09-Aug-18 08:43 AM
ミスによるデフォルトでの強のキャプチャを機械で防ぐんですね、なるほど、それなら僕の指摘は回避できそう。
Avatar
Kishikawa Katsumi 09-Aug-18 08:43 AM
self が解放されていてもそれが走ってしまいませんか?
これは私が今書いてるコードだと別にOKですね。
08:44
困る場合はさっきのやり方で早期リターン。
Avatar
Kuniwak 09-Aug-18 08:45 AM
うーん、Swift でましな Lint を実装したいという気持ちがずっとあるんですが、なかなか手をつけられない
Avatar
koher 09-Aug-18 08:45 AM
OK なケースがほとんどだと思いますが、解放されているときはクロージャが実行されないことを明確化するために冒頭で return したいような・・・。
Avatar
Kishikawa Katsumi 09-Aug-18 08:47 AM
{ [weak self] in self?.titleLabel.alpha = 0 self?.titleLabel.transform = CGAffineTransform(translationX: 0, y: labelHeight) }
こういう場合はいちいちguard書くよりはself?.の方が私はいいんじゃないかと思います。
😃 1
Avatar
Kuniwak 09-Aug-18 08:47 AM
その例はやばいですね。これだったら guard を上で羅列した方が見通しがいいです
Avatar
omochimetaru 09-Aug-18 08:47 AM
2文までは↑僕もそう書いてます、3文になるとguard let sself したくなります
😃 1
Avatar
Kuniwak 09-Aug-18 08:48 AM
ちなみに、別スレッドで reference count が 0 になって、あるスレッドの途中で解放されるケースとかってあるんでしょうか?
08:48
参照型を複数のスレッドで共有しているケースを想定しています
😲 1
Avatar
omochimetaru 09-Aug-18 08:49 AM
どういうことですか?どこかのスレッドで = nil されて 0 になれば、そのスレッドで deinit されますよ。
Avatar
koher 09-Aug-18 08:49 AM
↑の例で self?.titleLabel.alpha = 0 のときは生きてるけど self?.titleLabel.transform = ... では死んでることがあり得るかということですよね?
👌 1
Avatar
omochimetaru 09-Aug-18 08:50 AM
ありえますね。
😲 1
Avatar
Kishikawa Katsumi 09-Aug-18 08:50 AM
ありえますね。
😲 1
Avatar
Kuniwak 09-Aug-18 08:51 AM
そうですよね、だとすると guard let 羅列は途中に処理を挟むと稀に変な状況が発生するという辛いバグがありそう…
👍 1
Avatar
koher 09-Aug-18 08:52 AM
逆に、盲目的に冒頭で guard let していると、途中で解放されたときにそのクロージャからのみキャプチャされている状態になって、それで変なことになることがないかなというのが前から少し気になってました。
👍 1
Avatar
omochimetaru 09-Aug-18 08:53 AM
まあそうですけど、ViewControllerであれば、少なくともUIKit側からのretainの切断がメインスレッドでしかおこりえないので、さっきみたいなクロージャーがメインスレッドで実行される限り、実際のところそのパターンは生じない、って考えてます
🦀 1
👍 1
Avatar
Kuniwak 09-Aug-18 08:55 AM
私はよく Model 層のやつでも weak self してたので、この場合はなるべく guard let xxx = self は一箇所でまとめてやりたいですね
08:57
とりあえず、LLDB で再宣言 self が死ぬ問題の修正に向けてアップを始めたい…(あと Swift の Lint つくりたい…)
Avatar
N. 09-Aug-18 09:03 AM
(なるほどー👏
Avatar
tarunon 09-Aug-18 09:48 AM
そも論ですが成る可くselfキャプチャを作らないようにはしている
Avatar
Kuniwak 09-Aug-18 09:52 AM
うーん、なるほど。self キャプチャを作らない方法、思いつくのは Monad 的な purely functional なアプローチなのですが、それであっていますか? (edited)
Avatar
tarunon 09-Aug-18 11:44 AM
ベースはRACなのであってそうです。 (edited)
Avatar
koher 10-Aug-18 03:36 AM
昨日の話の続きで思ったんですが、 self に限らず weak キャプチャしたオブジェクトが異なるスレッドで解放される可能性がある場合、リファレンスカウントの減少から deinit の実行までは排他的でもアトミックでもないと思うんですが、そうすると weak キャプチャしてる側で常にぶっ壊れる可能性がないですか?異なるスレッドからの解放はそもそもやっちゃいけない?
03:37
たとえば、 self?.foo() を呼び出したときに、 self のリファレンスカウントをチェックしたときは 1 だったけど、 foo が呼ばれる前に別スレッドから self が解放されてしまったとか。
03:38
冒頭で guard let self = self else { return } してると一見安全そうだけど、この場合でもリファレンスカウントのチェックから代入してリファレンスカウント増やすまでの間に別スレッドから解放されてしまうおそれがありそう。 (edited)
Avatar
omochimetaru 10-Aug-18 03:38 AM
self?.foo() は fooを呼び出す前に self を retain するはずです
03:39
チェックして増やすところがアトミックなはず。
03:40
弱参照から強参照を取り出す操作ですね
Avatar
koher 10-Aug-18 03:40 AM
チェックして増やすところがアトミックなはず。
これはコンパイラを見ればわかる?ドキュメントに記載されてるっけ?
Avatar
omochimetaru 10-Aug-18 03:40 AM
確実にわかるのはそのへんはランタイム関数になってるからソース読めばわかりますね
Avatar
koher 10-Aug-18 03:42 AM
それが行われるのは weak の場合のみ?それとも ?. 全般?
Avatar
omochimetaru 10-Aug-18 03:43 AM
strongの ?. は その strong が生きてるので + 1 はいらんですね
Avatar
koher 10-Aug-18 03:44 AM
strong は要らなさそうだけど、 var foo: Foo? = Foo()foo が、 foo?.bar() を呼んでいる間に別スレッドから nil にされてしまう場合とかありそう。
03:44
実用上そういうケースはほぼないだろうけど、これは明確にやってはいけないことなのかどうか。
03:45
バランス的にはほとんどのケースで無駄だろうから、 strong のときは増減してなさそうだけど。
Avatar
omochimetaru 10-Aug-18 03:45 AM
あー、それは昔はあったので、+1しているかもしれない
03:45
いまは LoE で禁止されるはず
Avatar
koher 10-Aug-18 03:46 AM
てか、 ?. に限らない? foo.bar() でも foo が書き換えられてインスタンスが解放されることはあり得る?
Avatar
omochimetaru 10-Aug-18 03:46 AM
fooという変数それ自体へのアクセスが排他されていて、メソッド呼び出しはreadアクセスです
03:48
こういうのかな
03:48
do while で CAS ロックしてますね
03:48
下請けは C++ の std::atomic です
03:49
実は2017年の2月に参照カウンタの実装がガッツリ変更されていて、前見たときと実装が変わってた(本論とは無関係) (edited)
Avatar
koher 10-Aug-18 03:53 AM
だめだ C++ 力が足りなくて読めない・・・
03:58
いまは LoE で禁止されるはず
↓こういうのはどう?
import Dispatch class Foo { func bar() {} } var foo: Foo? = Foo() func a() { foo?.bar() foo = nil } func b() { foo?.bar() foo = nil } DispatchQueue.global(qos: .default).async { a() } DispatchQueue.global(qos: .default).async { b() }
03:59
strong だけどリファレンスカウント増やさないと死ぬケースがありそう。
Avatar
omochimetaru 10-Aug-18 03:59 AM
let old = refCount() let new do { if (checkZero) { return } new = old + 1 } while ( CAS (old, new) )
↑シンプルにこういう形ですよ
(edited)
04:00
CASロックループです
04:04
あー
04:04
参照型の変数はメソッド呼び出し中はアクセスじゃないのか
04:04
+1されてそうな気がしてきました
Avatar
koher 10-Aug-18 04:07 AM
↓の oldbits は参照なのか。
auto oldbits = refCounts.load(SWIFT_MEMORY_ORDER_CONSUME);
Avatar
omochimetaru 10-Aug-18 04:07 AM
Avatar
koher 10-Aug-18 04:09 AM
コピーだと何を排他しているの?
04:11
最も重要なのは、コンペア・アンド・スワップ(Compare and swap, CASと省略する)である。
Avatar
koher 10-Aug-18 04:13 AM
えっと、コピーだとそもそも何が共有されてるのかという質問でした。
Avatar
omochimetaru 10-Aug-18 04:14 AM
質問文の意味がわからないです、CASの基本イディオムを知らなくて話が通じていない気がしたので↑を貼った
04:15
↑のwikipediaのATMの例が
04:15
そのまんままさに同じアルゴリズムです
04:15
通帳の残高の代わりに参照カウンタを1増やしている (edited)
Avatar
koher 10-Aug-18 04:20 AM
えっと、 oldbitsnewbits が値だったら関数ローカルな存在でどことも共有されてないのでそもそも排他する必要がなくないということなんだけど、それ自体は値だけど中にポインタか参照を持ってるのかな?
Avatar
omochimetaru 10-Aug-18 04:23 AM
tryIncrement は 関数じゃなくて メソッドで
template <typename RefCountBits> class RefCounts { std::atomic<RefCountBits> refCounts; ... }
(edited)
04:24
参照型のオブジェクトはこの RefCounts をフィールドとして持っているので
04:24
このRefCountsを保持しているオブジェクト自体がスレッド間共有されています (edited)
04:25
oldbitsとnewbitsの型は RefCountBits だけどこれは RefCounts テンプレートクラスの型パラメーターで
04:25
厳密にはポインタになったりもするんですけど、値だと思えば良いです
Avatar
koher 10-Aug-18 04:26 AM
でも oldbitsnewbits は値型の関数ローカルの変数で、そこに書き戻したのがどうやってオブジェクトが保持している RefCounts に反映されてるの? (edited)
Avatar
omochimetaru 10-Aug-18 04:27 AM
while (!refCounts.compare_exchange_weak(oldbits, newbits, std::memory_order_relaxed));
↑ここのCASで書き戻してる
04:28
refCountsはRefCounts<RefCountBits>型が持っている std::atomic<RefCountBits>型のフィールドです。 (edited)
Avatar
koher 10-Aug-18 04:29 AM
refCountsoldBits を比較してるのか。
Avatar
koher 10-Aug-18 04:35 AM
やっとわかりました。 compare_exchange_weak が副作用のあるメソッドだとわかってなかった。
04:36
引数を参照でとって下記戻すのかと思ってた。
04:37
よく考えたら第三の値がないといけないんだから、それがレシーバーなのは当たり前か。
Avatar
omochimetaru 10-Aug-18 11:43 AM
@Loooop: Now I don't think adjacentPairs(circular: true) will pass the review: in the mind of many members of the forum, ad-hoc boolean arguments are not "swifty". While I wholeheartedly support the idea, it needs polish before we can convince the community. First, what if t...
11:43
2つずつ組にするやつ
Avatar
koher 12-Aug-18 05:58 AM
pair だけでいいのかなぁ。一般的に連続する N 要素の組にしてほしい気がする。
Avatar
omochimetaru 12-Aug-18 06:03 AM
僕もそれが気になったけど、提案はtupleになってるから、Nにするとたくさん用意しておくやつになりますね
Avatar
koher 12-Aug-18 12:59 PM
たくさん増やしておくやつになるとして、メソッド名に pair って入ってると辛そう。
Avatar
koher 13-Aug-18 04:03 AM
関数名やメソッド名が名詞だと↓みたいになって困ることないですか?
let foo = foo(at: path) // 名前が被ってコンパイルエラー
Avatar
Kishikawa Katsumi 13-Aug-18 04:05 AM
ありますねえ。
Avatar
koher 13-Aug-18 04:08 AM
どう対応してますか? self. で済むなら self. を付ける、関数はできるだけ作らない、とかでしょうか?
Avatar
omochimetaru 13-Aug-18 04:11 AM
名詞のルールを優先したいので 右辺にself. をつけて解決してます (edited)
Avatar
koher 13-Aug-18 04:12 AM
@omochimetaru 関数は?作らない?
Avatar
omochimetaru 13-Aug-18 04:15 AM
func foo(at: Path) を作る。
04:15
ん?
04:15
関数かメソッドかの議論ですか?
04:15
関数だと self がつけれないから?
Avatar
Kishikawa Katsumi 13-Aug-18 04:17 AM
selfをつけるか、スコープの短い変数ならlet f = foo(at: path)ですね。 そうじゃなかったらなんとか別の変数名を考える。
🙏 1
Avatar
omochimetaru 13-Aug-18 04:19 AM
グローバル関数の場合は渋い顔になりながら <ModuleName>.<funcName> って書く事もあるけど、 だいたいはなにかのクラスのメソッドになってて大丈夫です
Avatar
koher 13-Aug-18 04:39 AM
たしかに関数でもモジュール名を付けて書くことができるか。
Avatar
tarunon 13-Aug-18 01:56 PM
Result.Resultに破壊されてつらい
Avatar
omochimetaru 13-Aug-18 02:00 PM
パッケージ名とクラス名が同じだとそれ系でなんかできない事がある気がする
Avatar
tarunon 13-Aug-18 02:02 PM
public typealias Result =でexportできないとか
14:02
結構ありますね
Avatar
omochimetaru 13-Aug-18 02:02 PM
その問題を避けたかったのでFilePathって型を作るライブラリ作ったときは パッケージ名は FilePathFramework にした。 (edited)
Avatar
tarunon 13-Aug-18 02:03 PM
sつけるのいいなーとか思ってる
14:03
FilePaths
14:03
javaみがあるけど
Avatar
omochimetaru 13-Aug-18 02:04 PM
流行ってればそれでもいいな
Avatar
tarunon 13-Aug-18 02:04 PM
iOS人間だと○○Kit好きだよね
Avatar
omochimetaru 13-Aug-18 02:05 PM
Appleのがそうだしね
Avatar
omochimetaru 15-Aug-18 03:14 PM
このへんおもしろかった Data型をFoundationからstdlibに移そうぜスレ https://forums.swift.org/t/move-foundation-data-in-to-the-standard-library/15206 Foundationからネットワーク周りを切り離そうぜスレ https://forums.swift.org/t/pitch-move-urlsession-to-new-foundationnetworking-module/14002/1
This topic has come up a few times over the years, with apparently no objections. The standard library currently exposes no public type for an owned buffer which is released when its last reference becomes unreachable. Currently, the only facility for passing byte-buffers a...
Hi everyone, As we continue to push forward on completing swift-corelibs-foundation, I would like to propose a structural change to help us meet our goals: move URLSession and related types into a new library. Some of the feedback we've received from the SwiftNIO team is th...
👍 1
Avatar
norio_nomura 22-Aug-18 11:10 AM
自動生成されたDecodableのイニシャライザをサブクラスでオーバーライドできる様になってた。 @swift-4.1.3 @swift-4.2.4
import Foundation private class Person: Codable { let name: String init(name: String) { self.name = name } } private class Employee: Person { let id: Int init(name: String, id: Int) { self.id = id super.init(name: name) } enum CodingKeys: String, CodingKey { case id } required init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) id = try container.decode(Int.self, forKey: .id) try super.init(from: decoder) } override func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(id, forKey: .id) try super.encode(to: encoder) } }
(edited)
Avatar
swift41 BOT 22-Aug-18 11:10 AM
exit status: 1 with stderr:
<stdin>:29:19: error: method does not override any method from its superclass override func encode(to encoder: Encoder) throws { ~~~~~~~~ ^ <stdin>:28:1: error: 'required' initializer 'init(from:)' must be provided by subclass of 'Person' ^ <unknown>:0: note: 'required' initializer is declared in superclass here
(edited)
Avatar
swift42 BOT 22-Aug-18 11:10 AM
no output (edited)
Avatar
omochimetaru 22-Aug-18 11:12 AM
ほお。もともとは生成タイミングの問題があったんですかね
Avatar
norio_nomura 22-Aug-18 12:16 PM
Encodableのメソッドも同じだった。
Avatar
koher 28-Aug-18 01:39 AM
@dynamicMemberLookup@dynamicCallable に加えて、 @dynamicConvertible ほしくないですか?今だと PythonObject から Swift に戻すときに↓のようにしないといけなくて面倒。
import Python let np = Python.import("numpy") let a = np.array([[1, 2], [3, 4]]) let b = np.array([[5], [6]]) let c = np.matmul(a, b) let d: Int = Int(c[0, 0])! // ここで明示的変換が必要 print(d)
01:41
前提として Swift では暗黙の型変換は許さないという上で、 @dynamic 系は安全性を崩して書きやすさをとっているので、 dynamic に限って暗黙の型変換を許すのは良いバランスじゃないかということです。
01:41
↓のように書きたい。
import Python let np = Python.import("numpy") let a = np.array([[1, 2], [3, 4]]) let b = np.array([[5], [6]]) let c = np.matmul(a, b) let d: Int = c[0, 0] // 暗黙の型変換 print(d)
01:42
Int を右に書くか左に書くかの違いに見えますが、引数に渡すときに意味があります。
01:43
↓みたいな感じ。
@dynamicMemberLookup @dynamicCallable @dynamicConvertible struct PythonObject { ... func converted() -> Int { ... } func converted() -> Bool { ... } func converted() -> String { ... } func converted() -> (PythonObject, PythobObject) { ... } ... }
(edited)
01:44
今は IntBool 等については extensioninit になってるけど、タプルは extension 作れないので PythonObjecttuple2 とかのメソッドが生えてて統一感もない。
Avatar
omochimetaru 28-Aug-18 01:45 AM
どうして "dynamic" なんですか?
01:45
"dynamicMemberLookup"と"dynamicCallable"は、型チェックのときはなんでも通る事にしておいて、 実行時にメソッド名やプロパティ名を文字列として渡して
01:46
実行時にシグネチャレベルで動的にディスパッチする点がdynamicと思っていますが
01:46
その例だと普通に Int への暗黙変換 を要求しているように見えます
01:46
特にいま名前のニュアンスは重要でない?
Avatar
koher 28-Aug-18 01:47 AM
たしかにこれだと dynamic になってなさそうだな。乱用されないように dynamic に限定したい。 dynamic に限定して暗黙型変換がほしいという気持ちが先にあって、 converted の例は今適当に書いたから深く考えてなかった。 (edited)
Avatar
omochimetaru 28-Aug-18 01:48 AM
なるほど。
01:48
それだったら
Avatar
koher 28-Aug-18 01:49 AM
でも戻り値側から推論させて処理を分ける必要があるから↑のようにならざるを得ない?
01:49
@dynamicMemberLookup が付与されているときのみ @dynamicConvertible にできるとか?
Avatar
omochimetaru 28-Aug-18 01:49 AM
extension Int { init(_ : py PythonObject) }
↑これの実装+暗黙呼び出しがしたいって感じですかね init側じゃなくてconvert側でもいいけど
01:49
例えば
01:50
今ってNSDataとDataの相互変換とか
01:50
Dataに対してObjCBridgeable みたいな
01:50
プロトコルを定義して変換処理を設定しておくとできるってかんじだから
Avatar
koher 28-Aug-18 01:50 AM
@dynamicMemberLookup な型を引数にとる init(_:) があれば暗黙型変換とかいう機能でもいいのかもしれないけど (edited)
Avatar
omochimetaru 28-Aug-18 01:51 AM
dynamicMemberLookupかdynamicCallableがついてる型に対する変換プロトコルを表明できる機能+それの暗黙呼び出し
Avatar
koher 28-Aug-18 01:51 AM
それだとタプル(というか non-nominal )が対応できない
Avatar
omochimetaru 28-Aug-18 01:51 AM
ってかたちで、 Swift <-> ObjC ブリッジと同じカタチに整理できそうですね
01:51
あ〜
01:51
タプルね・・・
01:51
タプルも対応するとなると今まで無かった機能ですね。
01:52
DynamicCallableを使ってコードを書いてみたことがないからわからないけど、書いてみるとその変換の欲しくなるんかな (edited)
Avatar
koher 28-Aug-18 01:52 AM
@dynamic 系ってあえてプロトコルじゃなくしてあって
01:52
@dynamicCallablesubscript の引数って Dictionary じゃなくてもいいし、
01:53
それはプロトコルでも associatedtype でできるか
01:53
↑みたいな converted という名前で解決するパターンだと attribute と親和しそうなんよね。
01:54
@omochimetaru
DynamicCallableを使ってコードを書いてみたことがないからわからないけど、書いてみるとその変換の欲しくなるんかな
Swift の型→ PythonObject は暗黙的に変換されるから
(edited)
01:55
逆もほしくなる。
Avatar
omochimetaru 28-Aug-18 01:56 AM
Swift の型→ PythonObject は暗黙的に変換
dynamicMemberLookupのメソッドの引数に渡すときのことですよね?
01:56
PythonObjectを取る通常の関数に Int を渡す事はできないと思ってた
01:56
ん、いや、それも変か
Avatar
koher 28-Aug-18 01:57 AM
import Python let np = Python.import("numpy") let elements: [[Int]] = [[1, 2], [3, 4]] let a = np.array(elements) // OK
01:57
これは、 @dynamicCallablesubscript の引数の型が (edited)
01:57
PythonObject じゃなくて PythonConvertible になってるから。
Avatar
omochimetaru 28-Aug-18 01:58 AM
subscript?
Avatar
koher 28-Aug-18 01:58 AM
@dynamicCallable はメソッドコールを subscript に変換する。
Avatar
omochimetaru 28-Aug-18 01:58 AM
なるほど
01:59
[[Int]] が PythonConvertible として定義されてて、全部それで受け取るのか。 (edited)
Avatar
koher 28-Aug-18 01:59 AM
a = someValue(keyword1: 42, "foo", keyword2: 19)
a = someValue.dynamicallyCall(withKeywordArguments: [ "keyword1": 42, "": "foo", "keyword2": 19 ])
のシュガー。
Avatar
omochimetaru 28-Aug-18 01:59 AM
うーん、渡す側に変換がいらないのは
02:00
XxxConvertibleパターンなら、とくにdynamic関係なく、Swiftはいつもそうですよね
Avatar
koher 28-Aug-18 02:00 AM
[[Int]] が PythonConvertible として定義されてて、全部それで受け取るのか。(edited)
多分
extension Array: PythonConvertible where Element: PythonConvertible { ... }
だろうね。
Avatar
omochimetaru 28-Aug-18 02:00 AM
元の世界に戻してくるときには明示的な変換が必要なのは、普通。
Avatar
koher 28-Aug-18 02:01 AM
言語機能的にはそうだけど、安全性を捨てた dynamic な世界を導入してるのに、戻すところだけ安全にしても意味ない気が。 Python と Swift の世界を行き来するときに戻ってくるときだけ変換が必要で面倒・・・。
Avatar
omochimetaru 28-Aug-18 02:02 AM
ああそうか
02:02
x.toSwiftInt() みたいな事をやったところで
02:02
それが生えてるのか正当な変換なのかもよくわからないのか。
02:03
いやPythonObjectにはやしたら生えてることはわかるけど、中身の値の型との保証がないから。
Avatar
koher 28-Aug-18 02:03 AM
うん。今のところ、一応全部 Optional になってて、変換できなかったら nil が返ってくる
02:03
Int(pythonObject) も変換できなかったら nil
02:03
でもこれに失敗するケースってほぼ Logic failure だと思う。
Avatar
omochimetaru 28-Aug-18 02:04 AM
確かにそうですね
02:04
右辺の式に関してそもそも何も検査されてないから。
Avatar
norio_nomura 28-Aug-18 02:41 AM
暗黙型変換が失敗したらどういう挙動になるの?
let d: Int = c[0, 0] // 暗黙の型変換
02:46
Fatal errorになるのかな。
Avatar
koher 28-Aug-18 02:49 AM
Logic failure なので !precondition に失敗したときと同じイメージです。
Avatar
norio_nomura 28-Aug-18 03:07 AM
なるほど。
Avatar
norio_nomura 29-Aug-18 03:25 AM
Swiftへ移植したいCの参照実装が std::atomic とか使ってたのでstdlib内を探したら _stdlib_atomicCompareExchangeStrongPtr https://github.com/apple/swift/blob/master/stdlib/public/core/Runtime.swift.gyb#L25 とか見つけたのですが、stdlib内で使ってるところが見当たらず。何か違うメカニズムを使ったほうがよいのかな。
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
Avatar
omochimetaru 29-Aug-18 03:26 AM
移植というのはSwiftで書き直すという意味ですか?
Avatar
norio_nomura 29-Aug-18 03:27 AM
そう。SwiftBacktraceへ、お手軽にクラッシュハンドラを登録できるLLVMEnablePrettyStackTrace()みたいなのを付け加えようとしてるのです。
03:29
DarwinならこういうのがあるけどLinuxクロス要件もあるならう〜ん
03:30
In Windows, atomic operation functions are separated by 32bit and 64bit like this: InterlockedIncrement32 InterlockedIncrement64 Meanwhile, what functions do the same in Linux? What is the functi...
03:32
並列アルゴリズムならDispatchQueueを使うのが良いけど、 std::atomicみたいなローレベルな同期プリミティブになってくると
03:32
Swiftには標準が無いのか・・・? (edited)
Avatar
norio_nomura 29-Aug-18 03:33 AM
ざっと探した限り見当たらず。
Avatar
omochimetaru 29-Aug-18 03:34 AM
ランタイムの参照カウンタとかはC++だし、そうですよねえ
Avatar
norio_nomura 29-Aug-18 03:35 AM
あきらめて_stdlib_atomicCompareExchangeStrongPtr使います。
03:36
ありがとうございます。
Avatar
rintaro 03-Sep-18 03:13 AM
https://forums.swift.org/t/opaque-result-types/15645 Generalized Existential っぽいけどちょっと違う
func returnStringCollection() -> opaque Collection where _.Element == String
みたいなのを出来るようにする提案
(edited)
Hello all, Here's a proposal I've been thinking about for a while (I blame Rust), but which came up again due to the review of SE-0222. Now seems like a fine time to pitch it. The complete proposal follows, or you can go look at the rendered version. Introduction This propo...
👀 1
Avatar
koher 03-Sep-18 03:29 AM
これってコンパイル時にチェックできますか?
func makeOpaque<T>(_: T.Type) -> opaque Any { /* ... */ } var x = makeOpaque(Int.self) x = makeOpaque(Double.self) // error: "opaque" type from makeOpaque<Double> is distinct from makeOpaque<Int>
03:30
<T> で判断するのかな??
03:31
そういうことか。
Avatar
rintaro 03-Sep-18 03:32 AM
makeOpaque の実装知らないと判断できない気がするんですけど、モジュール跨いだときどうするんだろう。(まだ読んでない
Avatar
koher 03-Sep-18 03:34 AM
まだよくわかってないですが、なんとなく、ジェネリック関数でできることか、 generalized existential で実現できることしか実現できない気がしますが、そんなことないのかなぁ・・・。
03:35
↓これの最後の行はエラー??
protocol P { } extension Int : P { } extension String : P { } func f1() -> opaque P { return "opaque" } func f2() -> opaque P { return 42 } var a = f1() a = f2()
Avatar
norio_nomura 03-Sep-18 04:12 AM
実装詳細を隠すためにexistentialsを返す様にするとダイナミックディスパッチになってパフォーマンスが出ないけど、opaqueなら実装詳細を隠したままconcrete typeを使ってパフォーマンス出せるよ、って事かな?
04:17
↓これの最後の行はエラー??
concrete typeに出来なければエラー、みたいな制限がつくのかな?
(edited)
Avatar
omochimetaru 03-Sep-18 04:21 AM
半分ぐらいまで読んだ
04:23
Existentialと違ってコンパイルタイムには一つの型だから
04:24
func f() -> P { if Bool.random() { return 17 } else { return "hello, existential" } }
こういうのはできないってことらしい
04:24
func f() -> P { /* ... */ } func g() -> opaque P { /* ... */ } let fArray = [f(), f(), f()] // contains a mix of String and Int at run-time let gArray = [g(), g(), g()] // homogeneous array of g()'s opaque result type
04:24
let vf1 = f1() // type of vf1 is the opaque result type of f1()
04:24
関数名ごとに型が解決されて?ついてるから (edited)
04:25
↓これの最後の行はエラー??
それはエラーな気がする。
04:25
"opaque <Protocol>" で型なんじゃなくて、 "opaque <Protocol> from <Function>" ってことじゃないですか?
04:26
それで、解決してる真の型が同一であれば違う関数同士でも同一扱いな気がする。
Avatar
koher 03-Sep-18 05:45 AM
@omochimetaru その場合、 @rintaro さんが言うようにモジュールまたいだらエラーか判定できなくない?それとも、解決された型の情報を埋め込む?
Avatar
omochimetaru 03-Sep-18 05:47 AM
モジュールをビルドするときに、解決結果とインターフェースの埋め込みが必要でしょうね。 それか、解決した名前と、Generalized Existentialをそれように実装するか・・・?
05:48
Effect on API resilience Opaque result types are part of the result type of a function/type of a variable/element type of a subscript, which cannot be changed without affecting API resilience. We could allow an API originally specified using an opaque result type to later evolve to specify the specific result type. The result type itself would have to become visible to clients, and this might affect source compatibility, but (mangled name aside) such a change would be resilient.
05:48
結果の型それ自体はクライアントから可視になる必要があるだろう。 ( The result type...
(edited)
05:51
そしてそれはソース互換性に影響を与えるだろう、
but以降は英語がわからん
Avatar
rintaro 03-Sep-18 05:54 AM
However, the underlying concrete type can change from one version to the next without breaking ABI, because that type is not known to clients of the API.
真の型を変えても ABI が変わらないってことはー、コンパイル時に解決するというのと矛盾しているような。熟読しないとわからないでござる。
Avatar
omochimetaru 03-Sep-18 06:00 AM
そこの ABI、 APIのタイポじゃなかろうか・・・
Avatar
rintaro 03-Sep-18 06:03 AM
いや、Implementation strategy に、「opaque result type を使用するクライアントは、結果値のサイズ、アライメント、レイアウトなどは不明のものとして扱う必要がある」とあるので、型が不明な場合 まんま existential として扱うっぽい。
Avatar
omochimetaru 03-Sep-18 06:03 AM
なるほど
06:04
じゃあ、実装としては事実上Genralized Existentialが提供されるけど、言語文法としてはもうちょっと縛ったものになる、という感じ・・・?
Avatar
rintaro 03-Sep-18 06:05 AM
っぽいですね。 "Opaque result types are uniqued based on the function/property/subscript and any generic type arguments." なので、
それで、解決してる真の型が同一であれば違う関数同士でも同一扱いな気がする。
は違う。
Avatar
omochimetaru 03-Sep-18 06:06 AM
なるほどなるほど(あとで、ちゃんと読みます)
Avatar
koher 03-Sep-18 06:20 AM
それって、さっきの
var a = f1() a = f2()
が同一モジュール内はコンパイルエラーだけど、モジュールまたいだらコンパイル通るということになりませんか?
Avatar
rintaro 03-Sep-18 07:01 AM
同一モジュールでもエラーになると思います。
Avatar
koher 03-Sep-18 07:08 AM
モジュールをまたいでも、の間違いですか?
Avatar
rintaro 03-Sep-18 07:09 AM
ああ、質問の意味を取り違えてました。はい「モジュールをまたいでも」です。
Avatar
omochimetaru 04-Sep-18 04:06 AM
提案を読み直した
04:06
面白かったところ opaque result型はそれ自身がプロトコルに準拠できる
func foo<C: Collection>(_ : C) { } foo(c) // okay: unlike existentials, opaque types work with generics
04:07
返り値のopaque result型のconformanceを、ひとまとめにシグネチャだけオーバーロード(?)できる
extension BidirectionalCollection { public func reversed() -> opaque BidirectionalCollection where _.Element == Element where Self: RandomAccessCollection -> _: RandomAccessCollection where Self: MutableCollection -> _: MutableCollection { return ReversedCollection<Self>(...) } }
04:08
↑は3つのシグネチャが同時に書かれていて、 Selfによって、opaque resultが BidirectionalCollectionか、 RandomAccessCollectionか、MutableCollectionか、変わる
Avatar
tarunon 04-Sep-18 04:09 AM
HigherKindedの穴を埋めるのが目的なのかな (edited)
Avatar
omochimetaru 04-Sep-18 04:12 AM
いや、これはもともと、
struct ReversedCollection<C: BidirectionalCollection>: BidirectionalCollection {...} extension ReversedCollection: RandomAccessCollection where C: RandomAccessCollection {}
04:12
こういうふうにしてすでに実現できていた事なんだけど
04:12
↑だったら、ReversedCollection側の conditional conformanceで対応できていたことが
04:13
extension BidirectionalCollection { public func reversed() -> opaque BidirectionalCollection where _.Element == Element { return ReversedCollection<Self>(...) } }
(edited)
04:13
opaque化することで、 ↑このopaque BidirectionalCollectionが、 RandomAccessCollectionになることを記述できなくなるので
04:13
extension RandomAccessCollection { public func reversed() -> opaque RandomAccessCollection where _.Element == Element { return ReversedCollection<Self>(...) } }
04:13
冗長に↑も書かないといけなくなってしまう
04:13
という言語機能のデグレが起きるので、 それをカバーするもの。
Avatar
tarunon 04-Sep-18 04:14 AM
なるほど
Avatar
omochimetaru 04-Sep-18 04:15 AM
func h() -> opaque Comparable { return /* ... */ } var hArray = [h(), h(), h()] hArray.sort() // okay! the Element type is Comparable, and all types are the same
04:15
↑こっちは地味に新しくできるようになること
04:17
いままで AnyComparable を作ろうとしたら、 AnyComparableが2つあっても、それらを比較できなかった。 同じComparableが入ってるかわからんから。
04:22
Existentials do not allow such an operation, even with generalized existentials, because two values of the same existential type may have different types at runtime.
04:23
generalized existentialであってもそれができない、と言ってるから、この提案はGeneralized Existentialを超える良いアイデアって形で出てるのか・・・? なんでGEと別の話が湧いてきたのかよくわかっていない。
Avatar
koher 04-Sep-18 02:13 PM
Generics Manifesto は↓だから、新しい話が出てきてもおかしくなさそう。
It is not a plan for Swift 3, nor an official core team communication
01:17
生文字列通った
🎊 1
Avatar
koher 07-Sep-18 01:31 AM
これって SE-200 ってそんな古いプロポーザルだったのか。差し戻しがあったからか。
Avatar
omochimetaru 07-Sep-18 01:31 AM
最新が228だからそんなに古くも無いイメージ
Avatar
koher 07-Sep-18 01:32 AM
でも SE-0216 の @dynamicCallable でもずいぶん昔に通ったイメージ。
01:33
0018とか0030とか
01:33
ず〜〜〜〜っと進まなくて、
01:33
時々スレッドで「これどうなった?」「XXが終わらんと無理」
01:33
ってやってる
01:34
0026もちょくちょくみるな
Avatar
koher 07-Sep-18 01:34 AM
いやまあそういうのはあるとして、もっと新しいプロポーザルなのかと思ってた。
Avatar
omochimetaru 07-Sep-18 01:35 AM
なるほど
01:35
そうするとやっぱ一回戻った分ですね
01:35
確か、実例が足りない、とかで差し戻されたような。
Avatar
koher 07-Sep-18 01:43 AM
そっこーでマージされてる https://github.com/apple/swift/pull/17668
As per discussion in second pitch of raw strings on swift-evolution https://forums.swift.org/t/pure-bikeshedding-raw-strings-why-yes-again/13866. Work in progress, submitting now to get PR link. Re...
Avatar
omochimetaru 07-Sep-18 01:43 AM
この注射アイコンのジョーノさんめっちゃやってた
01:44
リジェクトされた旧仕様も実装してたような
01:44
01:44
てことはmasterでつかえるのか
Avatar
koher 07-Sep-18 01:45 AM
なんか rebase するかもめてるな。
01:45
Reverts apple/swift#19168 to reinstate apple/swift#17668 which missed a “squash” first time around. Implementation for SE-200
01:46
再マージされてた
Avatar
rintaro 07-Sep-18 07:23 AM
In https://github.com/apple/swift/pull/19151, I'm changing code generation for class convenience initializers so that they only have "allocating" entry points, which are responsible for allocating and initializing the entire object. (See Changing class convenience initializer...
❤ 2
Avatar
omochimetaru 07-Sep-18 07:41 AM
!!これはよく読まねば。
Avatar
omochimetaru 07-Sep-18 11:07 AM
プロトコル仲介しなくてもselfに代入できるようにするのか。 そしてワン猫サンプルをリンタロさんが書き込んでるw
😅 1
Avatar
tarunon 07-Sep-18 11:11 AM
ワン猫w
Avatar
omochimetaru 07-Sep-18 11:12 AM
ニャー犬と迷ったがワン猫が主流な気がした
Avatar
Biacco42 07-Sep-18 11:12 AM
ワン猫活躍してる
Avatar
koher 07-Sep-18 09:52 PM
21:53
ワン猫死んだ?
👀 1
Avatar
omochimetaru 08-Sep-18 03:47 AM
手が空いたら詳細を調べたい
Avatar
omochimetaru 10-Sep-18 02:50 AM
// $ swift -swift-version 5 protocol CopyInitializable { init(copy: Self) } extension CopyInitializable { init(copy: Self) { self = copy } } class Animal : CopyInitializable { convenience init(animal: Animal) { self.init(copy: animal) } }
02:50
a.swift:13:25: error: cannot convert value of type 'Animal' to expected argument type 'Self' self.init(copy: animal) ^~~~~~ as! Self
02:51
> おかしいのは、ここで self.init(_with: ) が呼び出せてしまうことじゃないですか? > AnimalProtocolが引数に受けてる Self は、 AnimalBase が final で無いのだから > 何かのサブクラスである可能性があって (たとえばCat ) > なのに、 obj: AnimalBase を渡せてしまっている
02:51
自分の考えと一致する方向で修正されている〜
🙌 1
Avatar
tarunon 11-Sep-18 01:20 PM
考え得る中で一番嬉しい修正に見える
Avatar
norio_nomura 11-Sep-18 01:31 PM
その修正、1年以上前なのね。 https://github.com/apple/swift/pull/11637
Consider a class initializer that delegates to a protocol extension initializer, for example protocol P {} extension P { init() { ... } } class C : P { convenience init(foo: Int) { self.init()...
Avatar
omochimetaru 11-Sep-18 05:01 PM
マジかw
Avatar
koher 12-Sep-18 02:21 PM
@swift-nightly -swift-version 5 Swift 5 、 NoError 要らずでいい感じ。
enum Result<Value, Error: Swift.Error> { case success(Value) case failure(Error) func get() throws -> Value { switch self { case .success(let value): return value case .failure(let error): throw error } } } extension Result where Error == Never { func get() -> Value { switch self { case .success(let value): return value } } } let a: Result<Int, Never> = .success(42) print(a.get())
👍 2
Avatar
swiftNightly BOT 12-Sep-18 02:21 PM
42
Avatar
omochimetaru 18-Sep-18 03:08 AM
@swift-4.2.4
enum Result<Value, Error: Swift.Error> { case success(Value) case failure(Error) func get() throws -> Value { switch self { case .success(let value): return value case .failure(let error): throw error } } } extension Result where Error == Never { func get() -> Value { switch self { case .success(let value): return value } } } let a: Result<Int, Never> = .success(42) print(a.get())
Avatar
swift42 BOT 18-Sep-18 03:08 AM
exit status: 1 with stderr:
<stdin>:15:30: error: same-type constraint type 'Never' does not conform to required protocol 'Error' extension Result where Error == Never { ^ <stdin>:24:8: error: type 'Never' does not conform to protocol 'Error' let a: Result<Int, Never> = .success(42) ^ <stdin>:17:9: error: switch must be exhaustive switch self { ^ <stdin>:17:9: note: add missing case: '.failure(_)' switch self { ^
Avatar
omochimetaru 18-Sep-18 03:08 AM
5系からNeverがBottomTypeとして振る舞うのか。
Avatar
tarunon 18-Sep-18 03:09 AM
嬉しいね
Avatar
kateinoigakukun 18-Sep-18 03:10 AM
undefinedが要らなくなります?
Avatar
tarunon 18-Sep-18 03:10 AM
いらない、fatalErrorでok
03:11
ただ、あれを使うとデフォルト引数にfile function lineを使えるメリットはある
Avatar
kateinoigakukun 18-Sep-18 03:11 AM
なるほど
Avatar
omochimetaru 18-Sep-18 03:12 AM
お、それもいけんの?
Avatar
tarunon 18-Sep-18 03:12 AM
Bottomならいける
Avatar
omochimetaru 18-Sep-18 03:12 AM
@swift-nightly -swift-version 5
let a: Int = fatalError()
Avatar
swiftNightly BOT 18-Sep-18 03:12 AM
exit status: 1 with stderr:
<stdin>:1:14: error: cannot convert value of type 'Never' to specified type 'Int' let a: Int = fatalError() ^~~~~~~~~~~~
Avatar
tarunon 18-Sep-18 03:12 AM
なんでやー
03:12
BottomTypeいうたやんか
Avatar
omochimetaru 18-Sep-18 03:12 AM
🤔
Avatar
Biacco42 18-Sep-18 03:12 AM
Avatar
omochimetaru 18-Sep-18 03:12 AM
BottomTypeになったわけではない。
Avatar
tarunon 18-Sep-18 03:13 AM
おそらくだが、protocol conformだけでは
Avatar
kateinoigakukun 18-Sep-18 03:13 AM
Errorに適合したわけではない? (edited)
Avatar
omochimetaru 18-Sep-18 03:13 AM
オーバーライドはどうなんだ、とか
03:13
サブタイピングにまつわる言語機能がたくさんあってアレ
Avatar
tarunon 18-Sep-18 03:14 AM
@swift-nightly -swift-version 5
protocol Animal {} func foo<A: Animal>(_ a: @autoclosure () -> A) {} foo(fatalError())
Avatar
swiftNightly BOT 18-Sep-18 03:14 AM
exit status: 1 with stderr:
<stdin>:3:1: error: global function 'foo' requires that 'Never' conform to 'Animal' foo(fatalError()) ^ <stdin>:2:6: note: where 'A' = 'Never' func foo<A: Animal>(_ a: @autoclosure () -> A) {} ^
Avatar
tarunon 18-Sep-18 03:14 AM
オオン
03:14
Errorだけすね
03:15
Errorとsynthesizerの入った幾つかのprotocolだけ特別になったくさい
Avatar
kateinoigakukun 18-Sep-18 03:17 AM
Bottom typeは夢だったのか…
Avatar
tarunon 18-Sep-18 03:17 AM
露と消えた
Avatar
omochimetaru 18-Sep-18 03:18 AM
@swift-nightly -swift-version 5
func f<E: Error>(_ e: E) {} f(fatalError())
(edited)
Avatar
swiftNightly BOT 18-Sep-18 03:18 AM
exit status: 4 with stderr:
<stdin>:2:3: warning: will never be executed f(fatalError()) ^ <stdin>:2:3: note: a call to a never-returning function f(fatalError()) ^ Fatal error: : file <stdin>, line 2 Current stack trace: 0 libswiftCore.so 0x00007f9510c6da50 _swift_stdlib_reportFatalErrorInFile + 115 1 libswiftCore.so 0x00007f9510bad167 <unavailable> + 3617127 2 libswiftCore.so 0x00007f95109c0785 <unavailable> + 1599365 3 libswiftCore.so 0x00007f9510bacf92 <unavailable> + 3616658 4 libswiftCore.so 0x00007f95109bf9bd <unavailable> + 1595837 5 libswiftCore.so 0x00007f9510b6581f <unavailable> + 3323935 6 libswiftCore.so 0x00007f95109bf149 <unavailable> + 1593673 8 swift 0x00000000010b39de <unavailable> + 13318622 9 swift 0x00000000010b7a62 <unavailable> + 13335138 10 swift 0x0000000000519d85 <unavailable> + 1154437 11 swift 0x00000000004ee6e5 <unavailable> + 976613 12 swift 0x00000000004e9aa1 <unavailable> + 957089 13 swift 0x0000000000494fa0 <unavailable> + 610208 14 libc.so.6 0x00007f9513136740 __libc_start_main + 240 15 swift 0x0000000000492dd9 <unavailable> + 601561 Stack dump: 0. Program arguments: /usr/bin/swift -frontend -interpret - -disable-objc-interop -swift-version 5 -module-name main #0 0x00000000044580a4 PrintStackTraceSignalHandler(void*) (/usr/bin/swift+0x44580a4) #1 0x0000000004455f70 llvm::sys::RunSignalHandlers() (/usr/bin/swift+0x4455f70) #2 0x0000000004458252 SignalHandler(int) (/usr/bin/swift+0x4458252) #3 0x00007f9514a0c390 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x11390) #4 0x00007f9510b65823 $Ss17_assertionFailure__4file4line5fla
(edited)
Avatar
omochimetaru 18-Sep-18 03:18 AM
んっ
03:18
@swift-nightly -swift-version 5
func f<X: Error>(_ error: X) {} f(fatalError())
Avatar
swiftNightly BOT 18-Sep-18 03:18 AM
exit status: 4 with stderr:
<stdin>:2:3: warning: will never be executed f(fatalError()) ^ <stdin>:2:3: note: a call to a never-returning function f(fatalError()) ^ Fatal error: : file <stdin>, line 2 Current stack trace: 0 libswiftCore.so 0x00007f6cf4244a50 _swift_stdlib_reportFatalErrorInFile + 115 1 libswiftCore.so 0x00007f6cf4184167 <unavailable> + 3617127 2 libswiftCore.so 0x00007f6cf3f97785 <unavailable> + 1599365 3 libswiftCore.so 0x00007f6cf4183f92 <unavailable> + 3616658 4 libswiftCore.so 0x00007f6cf3f969bd <unavailable> + 1595837 5 libswiftCore.so 0x00007f6cf413c81f <unavailable> + 3323935 6 libswiftCore.so 0x00007f6cf3f96149 <unavailable> + 1593673 8 swift 0x00000000010b39de <unavailable> + 13318622 9 swift 0x00000000010b7a62 <unavailable> + 13335138 10 swift 0x0000000000519d85 <unavailable> + 1154437 11 swift 0x00000000004ee6e5 <unavailable> + 976613 12 swift 0x00000000004e9aa1 <unavailable> + 957089 13 swift 0x0000000000494fa0 <unavailable> + 610208 14 libc.so.6 0x00007f6cf670d740 __libc_start_main + 240 15 swift 0x0000000000492dd9 <unavailable> + 601561 Stack dump: 0. Program arguments: /usr/bin/swift -frontend -interpret - -disable-objc-interop -swift-version 5 -module-name main #0 0x00000000044580a4 PrintStackTraceSignalHandler(void*) (/usr/bin/swift+0x44580a4) #1 0x0000000004455f70 llvm::sys::RunSignalHandlers() (/usr/bin/swift+0x4455f70) #2 0x0000000004458252 SignalHandler(int) (/usr/bin/swift+0x4458252) #3 0x00007f6cf7fe3390 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x11390) #4 0x00007f6cf413c823 $Ss17_assertionFailure__4file4line5fla
Avatar
omochimetaru 18-Sep-18 03:18 AM
oh
03:19
Errorプロトコルになったわけでもないのでは。死んでしまった。 (edited)
Avatar
tarunon 18-Sep-18 03:19 AM
@swift-nightly -swift-version 5
func f<X: Error>(_ error: @autoclosure ()->X) {} f(fatalError())
Avatar
swiftNightly BOT 18-Sep-18 03:19 AM
no output
Avatar
kateinoigakukun 18-Sep-18 03:19 AM
コンパイルは通ってるっぽい
Avatar
tarunon 18-Sep-18 03:19 AM
fatalで死んでるだけ
03:19
ややこしいからautoclosure使おう
Avatar
omochimetaru 18-Sep-18 03:19 AM
あ、これ実行されるからか。
03:19
良かった。
Avatar
tarunon 18-Sep-18 03:20 AM
つまりNeverはErrorになった
😇 3
😺 1
03:20
全部Errorに適合させたら実質BottomTypeでは?
03:21
天才
03:21
protocol Animal: Error {}
Avatar
kateinoigakukun 18-Sep-18 03:22 AM
T where T:Errorが無限に書かれる世界
Avatar
omochimetaru 18-Sep-18 03:22 AM
ErrorがbottomなんじゃなくてNeverがErrorだから違くない?
Avatar
tarunon 18-Sep-18 03:22 AM
マジレスするとNeverはErrorでAnimalはErrorなだけなので成り立たない
03:23
これと一緒
😇 1
Avatar
koher 18-Sep-18 04:12 AM
出遅れた。 NeverErrorEquatable になっただけで、 bottom になったわけではないはず。ただ、たしか Chris Lattner か Joe Groff が forum の議論の最初の方で bottom type に言及してた気が。
04:13
で、とりあえず今やることとして、 Equatable 入れるなら Error も入れるのがいいんじゃない?みたいな会話があったと思う。
Avatar
ikesyo 18-Sep-18 04:31 AM
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
👀 1
04:32
bottom typeについてはAlternatives consideredで言及されてあります (edited)
04:32
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
Avatar
omochimetaru 18-Sep-18 04:33 AM
This would have some advantages and might be ideal, but would require a lot more work to determine the design and implement the behavior.
04:33
否定的な観点は設計と実装の都合だけか、良かった
Avatar
ikesyo 18-Sep-18 04:33 AM
bottom type化に一気に行く前にとりあえずError, Equatable, Hashableを先にやったという感じ (edited)
Avatar
koher 18-Sep-18 04:42 AM
前に読んだのは↓っぽい。
Chris Lattner Jun 13 Moderate -1. Never is special because it has no instances - it is uninhabited by design. This means that it can conform to all protocols. I'd rather see a global solution rather than cherry picking these two specific protocols.
Joe_Groff Jun 13 If we're cherry-picking protocols to conform Never to, Error seems like another good one to whitelist, since it's useful to use Never to close off the error path in Result<T, Never>-like abstractions.
https://forums.swift.org/t/se-0215-conform-never-to-equatable-and-hashable/13586
(edited)
The review of SE-0215 — Conform Never to Equatable and Hashable begins now and runs through June 19, 2018. The proposal is authored by @mdiep. Reviews are an important part of the Swift evolution process. All review feedback should be either on this forum thread or, if yo...
Avatar
omochimetaru 18-Sep-18 06:05 AM
@swift-4.2.4
let range: Range<Float> = 0..<1 let x = range.randomElement()
Avatar
swift42 BOT 18-Sep-18 06:05 AM
exit status: 1 with stderr:
<stdin>:2:10: error: ambiguous reference to member 'randomElement(using:)' let x = range.randomElement() ^~~~~ Swift.Collection:11:17: note: found this candidate public func randomElement<T>(using generator: inout T) -> Self.Element? where T : RandomNumberGenerator ^ Swift.Collection:12:17: note: found this candidate public func randomElement() -> Self.Element? ^
Avatar
omochimetaru 18-Sep-18 06:05 AM
これなんで??
06:05
引数無いんだから2番目しか無いじゃんと思う
Avatar
rintaro 18-Sep-18 06:14 AM
Range<Float> は Collection じゃないので、実際には randomElement() 生えていないということだと思います。エラーメッセージも悪いし、Xcode で補完されちゃうのも悪い。
Avatar
omochimetaru 18-Sep-18 06:15 AM
あ〜、なるほど。
06:15
ありがとうございます。
Avatar
omochimetaru 21-Sep-18 03:18 AM
I need to start with a quick review of Swift's formal access semantics (as described in the ownership manifesto; reading just the three paragraphs under "Accesses" is fine). The evaluation of a storage reference expression in Swift is formally ordered like this: Formal eva...
03:19
ストレージアクセスの中断をどうするかって いうジョンマッコールのPitch
03:19
例えばcomputed propertyをinoutで渡している関数の中で例外が投げられた時
03:20
そのプロパティの書き換えはコミットされるのかされないのか。
03:20
コルーチンによるmodifyアクセサも仕様化されるからそれへの備えもありそう。
03:22
(いつも思うんだけど、mccallの長い英文、難しい・・・
Avatar
koher 27-Sep-18 01:58 AM
#swift-contrib から派生して、↓の挙動に驚いた。 @swift-4.2.4
var a = [2, 3, 5] var b = a[...] a.removeFirst() print(a.startIndex) b.removeFirst() print(b.startIndex)
Avatar
swift42 BOT 27-Sep-18 01:58 AM
0 1
Avatar
koher 27-Sep-18 01:59 AM
ArraySlicepopFirststartIndex を動かすけど、 removeFirst は動かさずに前に詰める(というか、先頭ポインタを動かして startIndex は動かさない)のかと思ってた。
Avatar
t.ae 27-Sep-18 02:00 AM
removeFirstpopFirstで返り値型が違うんですね
02:03
removeのほうは空だとFatal errorか。 結果的には詰めてもポインタ動かすだけでも同じなので計算量が少ない方を選ぶのは自然な気がしますね。
Avatar
koher 27-Sep-18 02:04 AM
@t.ae ArrayArraySlice の同じメソッドで startIndex が動くか動かないかという挙動が違う件ですね。
02:05
O(1) で startIndex が動かないようにも実装できるはず。
Avatar
t.ae 27-Sep-18 02:05 AM
結果的に同じというのは語弊がありますね。最終的な内容物が同じ
Avatar
koher 27-Sep-18 02:08 AM
Avatar
t.ae 27-Sep-18 02:13 AM
まだArraySliceremoveFirstの実装がどれなのか確定できてないですが上位プロトコルで実装されててArraySlice以外の事情も絡んでそうな気がしてます。 https://github.com/apple/swift/blob/ae6f5dd60460f340d98cf24c402c6489bb5a4f2b/stdlib/public/core/Collection.swift#L1765-L1781
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
Avatar
koher 27-Sep-18 02:14 AM
@swift-4.2.4
func foo<C: RangeReplaceableCollection>(_ collection: C) -> C.Index? { var collection = collection if collection.isEmpty { return nil} collection.removeFirst() return collection.startIndex } var a: Array<Int> = [2, 3, 5] var b: ArraySlice<Int> = a[...] print(foo(a)!) print(foo(b)!)
Avatar
swift42 BOT 27-Sep-18 02:14 AM
0 1
Avatar
koher 27-Sep-18 02:15 AM
これ微妙じゃないのかな?そこは未定義なんだと言えばそうなのかもしれないけど・・・。
Avatar
rintaro 27-Sep-18 02:19 AM
CollectionIndex は opaque として扱われるべきで、実値は気にするべきではないと思います。
Avatar
koher 27-Sep-18 02:29 AM
そういうものなんですね。まあ ArrayArraySlice は直接関係があるわけでないしいいのかな。
Avatar
koher 27-Sep-18 03:42 AM
例の opaque result types 、例に書かれてる↓みたいな記法になるんだったら generalized existential も似た記法になりそう。個人的には === が並んで読みづらい・・・。
var strings: opaque Collection where _.Element == String = ["hello", "world"]
03:44
Generalized existential の例として書かれてるのが
let strings: Any<Sequence where .Iterator.Element == String> = ["a", "b", "c"]
だから、書き換えたら↓みたいな感じ?
let strings: Sequence where _.Iterator.Element == String = ["a", "b", "c"]
03:44
opaque がなければ Generalized existential になるのか。
03:45
opaque が何かを Swift 初心者に説明するの難しそう・・・。
Avatar
koher 01-Oct-18 08:06 AM
二つのモジュール FooBar があって、両方に Cat という型があって、 Bar モジュールに Bar という型がある場合に、 Foo の中から Bar.Cat を表現するにはどうすればいいですか?↓のようにすると Bar.Bar.Cat を意味してしまってエラーになってしまいました。
// Foo モジュールにて import Bar struct Cat { init(_ cat: Bar.Cat) { ... } }
(edited)
08:09
import Bar as B とかできればいいんですが・・・。
Avatar
omochimetaru 01-Oct-18 08:24 AM
その問題、僕も困っていて、解決方法を知りたいんですよね。 なので、パッケージ名と、同じ名前の型をそのパッケージに定義しないのが良いと思っています。
08:24
Result は パッケージ名変えて欲しい。
Avatar
norio_nomura 01-Oct-18 08:32 AM
Fooのソースの中で必要とするのがBar.Catだけであれば、
import struct Bar.Cat
で解決できるかも。
Avatar
koher 01-Oct-18 08:41 AM
おおお、 @norio_nomura さんの方法そのままだと Foo.Cat と被ってしまったけど、別ファイルを作って
import struct Bar.Cat typealias BarCat = Bar.Cat
として BarCat としてアクセスできました。難点は、 BarCat を使う API が public な場合、 typealias を露出させないといけないこと。
Avatar
omochimetaru 01-Oct-18 08:45 AM
マジかそんな方法があったのか
Avatar
tarunon 01-Oct-18 08:46 AM
これってResult.Resultでも同じ方法できますか?
Avatar
koher 01-Oct-18 08:47 AM
試してないけどできそうな気がします。
Avatar
norio_nomura 01-Oct-18 08:48 AM
Hi, I have another Result structure in my code and it's conflicting with this one. How can I use Result.Result for this enum? I'm getting the error Reference to generic type 'Result'...
Avatar
tarunon 01-Oct-18 08:48 AM
おお
08:49
やっぱアンスコいりますよねぇ
Avatar
koher 01-Oct-18 08:50 AM
アプリ側で利用するならアンスコなしで typealias AntiResult<T, E: Error> = Result<T, E> とかでも良さそうな気も。
08:50
ライブラリだとアンスコ付けますね。
08:51
いや、もしかしたら typealias 露出しないでもいけるかな・・・ (edited)
Avatar
tarunon 01-Oct-18 08:51 AM
この間試してあんまりうまくいかなかった記憶
Avatar
koher 01-Oct-18 09:01 AM
やっぱ Result だと無理そう・・・
09:02
typealias 以前に、 norio さんが挙げてくれた方法も自モジュールで Result 型を宣言してたら無理そう。 (edited)
09:02
↑のリンクは、あくまで Alamofire で宣言されたものとの alias だから良いだけで。
09:03
さっき僕が挙げた例も、 Foo.CatBar.CatBar.Bar の問題だから回避できたけど、
09:03
Foo.BarBar.BarFoo の中で解決するのはきつそう。
Avatar
koher 02-Oct-18 08:35 AM
↓これの一つ目が 1 Cat にならないのってなんででしょう? 1 Animal の方のメソッドがジェネリックでないから? @swift-4.2.4
class Animal<T> {} class Cat<T, U>: Animal<T> {} struct Hoge { func foo(_: Animal<Hoge>) { print("1 Animal") } func foo<U>(_: Cat<Hoge, U>) { print("1 Cat") } } Hoge().foo(Cat<Hoge, Int>()) // 1 Animal func foo<T>(_: Animal<T>) { print("2 Animal") } func foo<T, U>(_: Cat<T, U>) { print("2 Cat") } foo(Cat<Hoge, Int>()) // 2 Cat
(edited)
Avatar
swift42 BOT 02-Oct-18 08:35 AM
1 Animal 2 Cat
(edited)
Avatar
koher 02-Oct-18 08:37 AM
PatialKeyPathWritableKeyPath でこのパターンでオーバーロードして死んだ。
Avatar
omochimetaru 02-Oct-18 08:44 AM
Comparing 2 viable solutions --- Solution #0 --- Fixed score: 0 0 0 0 0 0 0 0 0 0 0 ... Constraint restrictions: Cat<Hoge, Int> to Animal<Hoge> is [superclass] Cat<Hoge, Int> to Cat<Hoge, Int> is [deep equality] ... --- Solution #1 --- Fixed score: 0 0 0 0 0 0 0 0 0 0 0 ... Constraint restrictions: Cat<Hoge, Int> to Cat<Hoge, Int> is [deep equality] ...
08:45
comparing solutions 1 and 0 Comparing declarations func ffoo<U>(_: Cat<Hoge, U>) { } and func ffoo(_: Animal<Hoge>) { } comparison result: not better Comparing declarations func ffoo(_: Animal<Hoge>) { } and func ffoo<U>(_: Cat<Hoge, U>) { } comparison result: better
08:45
swift -Xfrontend -debug-constraints a.swift
08:45
比較して勝った事はわかるけどなんでなのかがよくわからないけど、↑の出力からわかる気がする
08:47
Comparing declarations func foo<T>(_: Animal<T>) { } and func foo<T, U>(_: Cat<T, U>) { } comparison result: not better Comparing declarations func foo<T, U>(_: Cat<T, U>) { } and func foo<T>(_: Animal<T>) { } (found solution 0 0 0 0 0 0 0 0 0 0 0) comparison result: better
(edited)
Avatar
koher 02-Oct-18 08:49 AM
もちろん比較して勝ってるから選ばれてるんだけど、この挙動は意図的なのかな?
08:49
↓ Kotlin の場合
open class Animal<T> class Cat<T, U>: Animal<T>() class Hoge { fun foo(a: Animal<Hoge>) { println("1 Animal") } fun <U> foo(a: Cat<Hoge, U>) { println("1 Cat")} } fun <T> foo(a: Animal<T>) { println("2 Animal") } fun <T, U> foo(a: Cat<T, U>) { println("2 Cat") } fun main(args: Array<String>) { Hoge().foo(Cat<Hoge, Int>()) // 1 Cat foo(Cat<Hoge, Int>()) // 2 Cat }
(edited)
Avatar
omochimetaru 02-Oct-18 08:49 AM
その詳細が、↑のデバッグ出力から読み取るんじゃないかと思って。
Avatar
koher 02-Oct-18 08:49 AM
なるほど
08:50
この場合 1 Cat が自然だと思うんだけどなぁ。
Avatar
omochimetaru 02-Oct-18 08:50 AM
1については、Genericメソッドよりnon genericメソッドが常に優先するルールな気がします
08:51
2はGenericメソッド同士だからそこは同ランクで、次の比較が引数の型が詳細な方、かなあ。
08:51
どっかに文書化されてましたっけ
Avatar
koher 02-Oct-18 08:51 AM
それがサブクラスで特殊化されてるのより強いのが納得いかない。
08:52
文書はわからないです。
08:53
もし non generic が常に強いとすると、 PartialKeyPath<T> と、そのサブクラスである KeyPath<T, U>WritableKeyPath<T, U> でオーバーロードして、 TSelf とか入れたときに後者が勝つ方法がなさそう。
08:53
UAny にしてしまえば勝てるだろうけど・・・。 (edited)
08:54
だめか? Any にしても variance がうまく働かない?
08:55
ダメっぽい。 @swift-4.2.4
let a: KeyPath<[Int], Int> = \[Int].count let b: KeyPath<[Int], Any> = a
Avatar
swift42 BOT 02-Oct-18 08:55 AM
exit status: 1 with stderr:
<stdin>:2:30: error: cannot convert value of type 'KeyPath<[Int], Int>' to specified type 'KeyPath<[Int], Any>' let b: KeyPath<[Int], Any> = a ^
Avatar
omochimetaru 02-Oct-18 08:56 AM
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
08:56
// A concrete type is better than an archetype. // FIXME: Total hack. if (type1->is<ArchetypeType>() != type2->is<ArchetypeType>()) { if (type1->is<ArchetypeType>()) ++score2; else ++score1; continue; }
08:56
これかなあ?
Avatar
koher 02-Oct-18 08:57 AM
それっぽい感じはするね。
Avatar
omochimetaru 02-Oct-18 08:57 AM
@ukitaka この辺わかりますか〜
Avatar
ukitaka 02-Oct-18 09:05 AM
ぱっとはわからんです、あとでみます〜
🙏 2
Avatar
koher 02-Oct-18 09:06 AM
↓最小ケースできた。 @swift-4.2.4
class Animal {} class Cat<T>: Animal {} func foo(_: Animal) { print("Animal") } func foo<T>(_: Cat<T>) { print("Cat") } foo(Cat<Int>())
Avatar
swift42 BOT 02-Oct-18 09:06 AM
Animal
Avatar
omochimetaru 02-Oct-18 09:18 AM
@swift-4.2.4
class Animal { func fooImpl() { print("Animal") } } class Cat<T>: Animal { override func fooImpl() { print("Cat") } } func foo(_ animal: Animal) { animal.fooImpl() } func foo<T>(_ cat: Cat<T>) { cat.fooImpl() } foo(Cat<Int>())
Avatar
swift42 BOT 02-Oct-18 09:18 AM
Cat
Avatar
omochimetaru 02-Oct-18 09:19 AM
こういうワークアラウンドを思いついたけど、PartialKeyPathは既存の型だから無理ですねえ
Avatar
koher 02-Oct-18 09:20 AM
func foo<T> 意味ないw
Avatar
omochimetaru 02-Oct-18 09:20 AM
func foo(_ animal: Animal) func foo<T>(_ cat: Cat<T>)
09:21
↑この2つがあるときに、foo<T> って完全に腐ってる?
Avatar
koher 02-Oct-18 09:23 AM
@omochimetaru @swift-4.2.4
class Animal {} class Cat<T>: Animal {} func foo(_: Animal) { print("Animal") } func foo<T>(_: Cat<T>) { print("Cat") } let f: (Cat<Int>) -> Void = foo f(Cat<Int>())
Avatar
swift42 BOT 02-Oct-18 09:23 AM
Cat
Avatar
omochimetaru 02-Oct-18 09:24 AM
なるほど・・・
Avatar
koher 02-Oct-18 09:25 AM
でもこれで普通に書いて Animal 優先は辛い・・・
Avatar
omochimetaru 02-Oct-18 09:25 AM
無意味にパラメータを足したりしようとしたけどダメだった(コンパイルが通らない
Avatar
koher 02-Oct-18 09:27 AM
↓なら Cat @swift-4.2.4
class Animal {} class Cat<T>: Animal {} func foo<X>(_: X, _: Animal) { print("Animal") } func foo<X, T>(_: X, _: Cat<T>) { print("Cat") } foo((), Cat<Int>())
Avatar
swift42 BOT 02-Oct-18 09:27 AM
Cat
Avatar
omochimetaru 02-Oct-18 09:27 AM
呼び出し側で埋める必要が出てしまう
Avatar
koher 02-Oct-18 09:27 AM
はい。
09:28
09:28
そこをデフォルト引数とかできないかな?
Avatar
omochimetaru 02-Oct-18 09:28 AM
やってみたんだけど、だめ
Avatar
rintaro 02-Oct-18 09:28 AM
@swift-4.2.4
class Animal {} class Cat<T>: Animal {} func foo<T: Animal>(_: T) { print("Animal") } func foo<T>(_: Cat<T>) { print("Cat") } foo(Cat<Int>())
Avatar
swift42 BOT 02-Oct-18 09:28 AM
Cat
Avatar
koher 02-Oct-18 09:28 AM
Never が bottom でも無理? 無理か。初期値に入れられない。 (edited)
Avatar
omochimetaru 02-Oct-18 09:28 AM
Avatar
koher 02-Oct-18 09:29 AM
なるほど・・・
Avatar
rintaro 02-Oct-18 09:29 AM
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
Avatar
omochimetaru 02-Oct-18 09:30 AM
おー。
Avatar
koher 02-Oct-18 09:32 AM
@rintaro これって意図的なのか、今実装がそうなってるだけなのかってわかります? AnimalCat<T> だと Cat<T> を優先してほしいのが自然な感覚な気がするんですが、継承で型パラを足すというのがレアケースなので考慮漏れの可能性もあるかなと思うんですが。確か、初期の Swift は継承で型パラ足すのできなかったですよね?
Avatar
rintaro 02-Oct-18 09:35 AM
初期の Swift は継承で型パラ足すのできなかったですよね?
これは覚えてないですが、フォーマルな仕様が無い以上、意図的か否かを気にすることに意味は無いと思います。
Avatar
koher 02-Oct-18 09:36 AM
バグレポ投げて意見を聞いてみるとかがいいですか?
Avatar
rintaro 02-Oct-18 09:36 AM
とはいえ、これ変更するとレアケースとはいえ Source Breaking になるので、なかなかハードル高いとは思います。
09:36
バグレポで良いと思いますよ 👍
🙂 1
Avatar
koher 02-Oct-18 09:38 AM
バグレポ出してみます。あと、とりあえず現状の問題は @rintaro さんのワークアラウンドで解決できました。ありがとうございました。
Avatar
koher 02-Oct-18 10:11 AM
👍 3
Avatar
rintaro 02-Oct-18 10:35 AM
僕だったら意図的か否かを訊かずに、"I believe the latter should be selected." と主張してしまいます🙃
🙂 1
Avatar
tarunon 02-Oct-18 10:51 AM
意図的ですか?は京都弁っぽさを感じるw
😅 1
Avatar
omochimetaru 02-Oct-18 10:52 AM
思いつかなかったけど、non generic優先が好ましいと思えるパターンはあるのかな
Avatar
rintaro 02-Oct-18 10:54 AM
同じくおもいつかなかったけど、これ Animalprotocol の場合も同結果になるのは結構きついと思った。 (edited)
10:57
↑気づかずに非効率な方に流されちゃってる場合が結構ありそう。という意味で。
Avatar
omochimetaru 02-Oct-18 11:01 AM
なるほど。継承避けてプロトコル指向で組んでても踏むかもしれない・・
Avatar
rintaro 02-Oct-18 05:44 PM
お、
Mark Lacey is working on improving this situation.
Avatar
omochimetaru 03-Oct-18 01:36 AM
non genericかgenericかどうかは優先度に影響しないようになるのかな
Avatar
koher 03-Oct-18 02:39 AM
Swift Bugs 、リアクションで絵文字付ける機能ないけど、こういうとき、いいね的なコメントをすべきなのか迷う。ゴミになる気もするし。絵文字一つだけのコメントを投稿すればいいのかな・・・。リアクションがないと見てないみたいだし。
Avatar
omochimetaru 03-Oct-18 06:19 AM
絵文字リアクションなんて昔は無かったのに・・・
Avatar
tarunon 03-Oct-18 06:19 AM
そもそも絵文字が存在してない
Avatar
omochimetaru 03-Oct-18 06:19 AM
慣れすぎて無くて困ってる人だ。
Avatar
tarunon 03-Oct-18 06:19 AM
Githubのリアクションも絵文字のバリエーションが足りなくて困る
Avatar
omochimetaru 03-Oct-18 06:19 AM
ウケる
Avatar
tarunon 03-Oct-18 06:20 AM
なんで👎😕 しかないんや
Avatar
koher 03-Oct-18 06:31 AM
わかる < Githubのリアクションも絵文字のバリエーションが足りなくて困る
Avatar
r_plus 09-Oct-18 05:32 AM
Xcode 9/Swift 4.1.2ではコンパイル通ってたコードで、Xcode 10にしたらSwift 4.2でも4.1でもコンパイラがSEGVするのに出会って、結局ジェネリクスにする必要が今のところなかったのでパターン2の方向で対応したんですが、ジェネリクス使ったままコンパイル通す方法とかありそうでしょうか。 https://gist.github.com/r-plus/3c5076c1f1c314cec0fe88536ea12159
Swift compiler SEGV in Xcode10. GitHub Gist: instantly share code, notes, and snippets.
Avatar
omochimetaru 09-Oct-18 06:19 AM
class A {} protocol BProtocol { associatedtype Info: A var info: Info? { get set } } class B<T1: A>: BProtocol { var info: T1? } protocol CProtocol { associatedtype Property: BProtocol var property: Property? { get set } } class C<T2>: CProtocol where T2 : BProtocol { var property: T2? }
06:20
ちょっと情報は落ちちゃってますがコレで通りました。
Avatar
tarunon 09-Oct-18 07:24 AM
めっちゃいいおやつなんだけどタスク積んでるから待って
Avatar
r_plus 09-Oct-18 08:13 AM
おぉ、なるほど。whereにするといけるのか。 <T2: B<A>> で二重になってたのが悪かったんですかね、やっぱり。
Avatar
omochimetaru 09-Oct-18 08:14 AM
いえ、 CのT2の制約を B から BProtocol に変更してます
08:15
class A {} protocol BProtocol { associatedtype Info: A var info: Info? { get set } } class B<T1: A>: BProtocol { var info: T1? } protocol CProtocol { associatedtype Property: BProtocol var property: Property? { get set } } // vvvvvvvv ここが違う class C<T2 : BProtocol>: CProtocol { var property: T2? }
(edited)
08:18
二重になってたのが悪かったんですかね
(それを書く事自体は)悪くはないはずで、コンパイラのバグとして bugs.swift.org に報告するのが良いと思います
(edited)
Avatar
r_plus 09-Oct-18 08:25 AM
<T2: BProtocol> にしても当初表現したかった形としては成立してるので、その形に修正しようかな。。ありがとうございます。
Avatar
rintaro 09-Oct-18 08:26 AM
最新 master ではコンパイル通ったので放っておいても直ると思いますが、再現コードがあると嬉しいので、bugs.swift.org は有り難いです。
Avatar
r_plus 09-Oct-18 08:29 AM
お、わかりました、最新では通るということはresolvedでしょうけど類似探してなければあげておきます。
Avatar
norio_nomura 09-Oct-18 12:50 PM
最新 master ではコンパイル通ったので放っておいても直る
Swift 5っていつ頃リリース予定でしたっけ?
Avatar
koher 09-Oct-18 09:57 PM
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
21:57
例年通りなら春頃?
Avatar
norio_nomura 09-Oct-18 10:18 PM
おお、そんなところに記載が。ありがとうございます。
🙂 1
Avatar
mono 10-Oct-18 11:55 AM
例年のSwiftの大きめの春リリースはSpring表記(Swift 2.2も3.1もその表記で3月でした)だったので、Swift 5のEarly表記ならもう少し早めかなと思っていました(英語の意味的には多分1-3月指していて、少し手こずって結局同じく3月になる可能性とかもありそうですが)。 - https://github.com/apple/swift-evolution/blob/9dd726f331629e64470ca99bc8986c89b60b35bc/README.md#development-minor-version--swift-22 - https://swift.org/blog/swift-3-1-release-process/
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
This post describes the goals, release process, and estimated schedule for Swift 3.1.
Avatar
koher 11-Oct-18 01:44 AM
early って初頭なんですね。前半くらいの意味かと思ってました。
Avatar
mono 11-Oct-18 02:39 AM
はい、明確な定義は無さそう(初めの四半期くらいと言っている人もいましたが)ですが、早めのニュアンスだと思いました。 (edited)
✅ 1
Avatar
koher 12-Oct-18 08:41 AM
Optional Chaining が Optional を flatten することが引き起こすちょっと微妙な(おもしろい?)例。 @swift-4.2.4
func foo(_ x: [Int?]?) -> Any { return x?[0] as Any } func bar<T>(_ x: [T]?) -> Any { return x?[0] as Any } let a: [Int?]? = [2, 3, 5] print(String(describing: foo(a))) print(String(describing: bar(a)))
(edited)
👀 1
Avatar
swift42 BOT 12-Oct-18 08:41 AM
Optional(2) Optional(Optional(2))
(edited)
Avatar
koher 12-Oct-18 08:42 AM
↑この前話してた Optional Chaining と flatten に絡んで > @omochimetaru (edited)
08:43
一見 TInt? を埋めたら同じコードに見えるけど結果が異なる。
Avatar
omochimetaru 12-Oct-18 08:43 AM
うーむなるほど ジェネリックなTのときはflattenしないからか。 (edited)
Avatar
koher 12-Oct-18 08:44 AM
今コード書いてて思い付いた。
Avatar
vicktorManuel 13-Oct-18 03:24 AM
面白い
Avatar
vicktorManuel 13-Oct-18 05:28 PM
@swift-4.2.4
enum Sample<T> { case Foo(T) case Bar(T) } indirect enum Sample1<T> { case Foo(T) case Bar(T) } enum Sample2<T> { indirect case Foo(T) case Bar(T) } enum Sample3<T> { indirect case Foo(T) indirect case Bar(T) }
`
Avatar
swift42 BOT 13-Oct-18 05:28 PM
no output
Avatar
vicktorManuel 13-Oct-18 05:36 PM
Recursive Enumerations
17:40
@swift-4.2.4
enum ArithmeticExpression { case number(Int) indirect case addition(ArithmeticExpression, ArithmeticExpression) indirect case multiplication(ArithmeticExpression, ArithmeticExpression) } let five = ArithmeticExpression.number(5) let four = ArithmeticExpression.number(4) let sum = ArithmeticExpression.addition(five, four) let product = ArithmeticExpression.multiplication(sum, ArithmeticExpression.number(2)) print(sum) print(product)
`
Avatar
swift42 BOT 13-Oct-18 05:40 PM
addition(main.ArithmeticExpression.number(5), main.ArithmeticExpression.number(4)) multiplication(main.ArithmeticExpression.addition(main.ArithmeticExpression.number(5), main.ArithmeticExpression.number(4)), main.ArithmeticExpression.number(2))
Avatar
vicktorManuel 13-Oct-18 05:44 PM
@swift-4.2.4
enum ArithmeticExpression { case number(Int) indirect case addition(ArithmeticExpression, ArithmeticExpression) indirect case multiplication(ArithmeticExpression, ArithmeticExpression) } let five = ArithmeticExpression.number(5) let four = ArithmeticExpression.number(4) let sum = ArithmeticExpression.addition(five, four) let product = ArithmeticExpression.multiplication(sum, ArithmeticExpression.number(2)) func evaluate(_ expression: ArithmeticExpression) -> Int { switch expression { case let .number(value): return value case let .addition(left, right): return evaluate(left) + evaluate(right) case let .multiplication(left, right): return evaluate(left) * evaluate(right) } } print(evaluate(product))
`
Avatar
swift42 BOT 13-Oct-18 05:44 PM
18
Avatar
omochimetaru 18-Oct-18 01:45 AM
Hi all, I wrote an Automatic Differentiation Manifesto, as the start to push for world's first general-purpose differentiable programming language.
01:46
Swift for TensorFlow の自動微分機能の、本家Swift向けのPitchが出た。
Avatar
omochimetaru 18-Oct-18 06:35 AM
class A<E> { convenience init<X>(_ array: [X]) where X : Equatable, X == E { self.init(array, { (a, b) in a == b }) } init(_ array: [E], _ eq: @escaping (E, E) -> Bool) {} }
Same-type requirement makes generic parameters 'X' and 'E' equivalent
これコンパイル通らないんですが、簡単な方法って無いんでしょうか
(edited)
06:36
ちなみにinitじゃなくてstatic funcならイケました。
Avatar
kateinoigakukun 18-Oct-18 06:40 AM
extension A where E: Equatable の中に生やすとか?
Avatar
omochimetaru 18-Oct-18 06:41 AM
あ〜できたー
06:41
なるほどそうか・・・ ありがとう〜
🙌 1
Avatar
omochimetaru 18-Oct-18 11:25 AM
@swift-4.2.4
struct KeySortedArray<Element, Key : Comparable> { init(_ array: [Element], _ getKey: @escaping (Element) -> Key) {} } extension KeySortedArray where Element : Comparable, Element == Key { init(_ array: [Element]) { } } class Cat { init() { KeySortedArray(self.blocks, { $0.time }) } }
Avatar
swift42 BOT 18-Oct-18 11:25 AM
exit status: 11 with stderr:
#0 0x000000000410b054 PrintStackTraceSignalHandler(void*) (/usr/bin/swift+0x410b054) #1 0x0000000004108ee2 llvm::sys::RunSignalHandlers() (/usr/bin/swift+0x4108ee2) #2 0x000000000410b202 SignalHandler(int) (/usr/bin/swift+0x410b202) #3 0x00007f0b420d2390 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x11390) #4 0x00000000016b1b09 swift::FunctionType::get(swift::Type, swift::Type, swift::AnyFunctionType::ExtInfo const&) (/usr/bin/swift+0x16b1b09) #5 0x00000000017fde74 swift::GenericFunctionType::substGenericArgs(swift::SubstitutionMap const&) (/usr/bin/swift+0x17fde74) #6 0x00000000017fdd02 swift::GenericFunctionType::substGenericArgs(llvm::ArrayRef<swift::Substitution>) (/usr/bin/swift+0x17fdd02) #7 0x000000000147abe0 swift::UncurriedCandidate::UncurriedCandidate(swift::ValueDecl*, unsigned int) (/usr/bin/swift+0x147abe0) #8 0x000000000147da0f swift::CalleeCandidateInfo::collectCalleeCandidates(swift::Expr*, bool) (/usr/bin/swift+0x147da0f) #9 0x00000000014667e1 (anonymous namespace)::FailureDiagnosis::visitApplyExpr(swift::ApplyExpr*) (/usr/bin/swift+0x14667e1) #10 0x000000000144d4d6 swift::ASTVisitor<(anonymous namespace)::FailureDiagnosis, bool, void, void, void, void, void>::visit(swift::Expr*) (/usr/bin/swift+0x144d4d6) #11 0x0000000001446642 swift::constraints::ConstraintSystem::diagnoseFailureForExpr(swift::Expr*) (/usr/bin/swift+0x1446642) #12 0x000000000144cb76 swift::constraints::ConstraintSystem::salvage(llvm::SmallVectorImpl<swift::constraints::Solution>&, swift::Expr*) (/usr/bin/swift+0x144cb76) #13 0x0000000001352138 swift::TypeChecker::solveForExpression(swift::Expr*&, swift::DeclContext*, swift::Type, swift::FreeTypeVariableBinding, swift::ExprTypeCheckListener*, swift::constraints::ConstraintSystem&, llvm::SmallVectorImpl<swift::constraints::Solution>&, swift::OptionSet<swift::TypeCheckExprFlags, unsigned int>) (/usr/bin/swift+0x1352138) #14 0x0000000001356465 swift::TypeChecker::typeCheckExpression(swift::Ex
Avatar
omochimetaru 18-Oct-18 11:25 AM
コンパイラ死ぬコード見つけた
11:26
コード自体壊れてるので、実害?は無い?けど。
Avatar
vicktorManuel 18-Oct-18 05:17 PM
@swift-4.2.4
let display.Name: String = "hola" print(display.Name)
`
Avatar
swift42 BOT 18-Oct-18 05:17 PM
exit status: 1 with stderr:
<stdin>:2:12: error: consecutive statements on a line must be separated by ';' let display.Name: String = "hola" ^ ; <stdin>:2:17: error: consecutive statements on a line must be separated by ';' let display.Name: String = "hola" ^ ; <stdin>:2:17: error: expected expression let display.Name: String = "hola" ^ <stdin>:2:5: error: type annotation missing in pattern let display.Name: String = "hola" ^ <stdin>:2:13: error: reference to member 'Name' cannot be resolved without a contextual type let display.Name: String = "hola" ~^~~~
Avatar
omochimetaru 22-Oct-18 04:20 AM
SwiftってdeinitがあるからRAIIパターンが書けるっていうメリットがあるとされてると思うんですが、 例えばinitでファイルハンドルを開いてdeinitで閉じるようなパターンを実装する時、 閉じるときに生じた例外をハンドリングできないという問題があると思ってて それについて最近思ったのが、 deinitがthrowsつけられてもよいのでは?ということで そうすると、throwing deinitな型をスコープに持っている関数がthrows化するのと、 そういう型の var に対する代入文が throws化するんだけど、 どう思います?
04:21
func writeData() throws { // ここにclose失敗のthrowsが必要, スコープ脱出時だからtry catchはできない let stream = try OutputStream() try stream.write("aaa") }
(edited)
Avatar
tarunon 22-Oct-18 04:21 AM
直感曰くクラスフィールドに持たせた時に難しそう
Avatar
omochimetaru 22-Oct-18 04:21 AM
setterがthrows付きになる
04:21
あとsubscriptもか。
04:21
現状仕様だとそれが通らんね・・・
Avatar
tarunon 22-Oct-18 04:22 AM
throws deinitをフィールドに持つならそのクラスもthrows deinit扱いにする必要があるが
Avatar
omochimetaru 22-Oct-18 04:22 AM
お、たしかに。
Avatar
tarunon 22-Oct-18 04:22 AM
シェアされている場合もありなかなか難しそうだ
Avatar
omochimetaru 22-Oct-18 04:23 AM
stored propertyで持っている場合は throws deinit が伝搬するけど、 computed property の場合はそうではないね
Avatar
tarunon 22-Oct-18 04:24 AM
現状だとどうするのが良いのかな
04:24
errorhandlerをアタッチするしか無い?
Avatar
omochimetaru 22-Oct-18 04:24 AM
deinitから外に通知するしか無いと思う
Avatar
tarunon 22-Oct-18 04:25 AM
deinit時はproperties全部生きてるよね、errorHandlerで良さそうかなとは思う
Avatar
omochimetaru 22-Oct-18 04:25 AM
生きてる
Avatar
koher 22-Oct-18 04:27 AM
スコープ脱出時だからtry catchはできない
これについては do で囲んだらちょうどスコープ脱出時になるのでは?
Avatar
omochimetaru 22-Oct-18 04:27 AM
お、たしかに。
04:27
変数を置くためのスコープを作るdoがcatch用のdoと共用できますね
Avatar
koher 22-Oct-18 04:27 AM
do { let stream = try OutputStream() try stream.write("aaa") } catch ... { // stream が破棄されて deinit の throws も catch }
04:28
変数を置くためのスコープを作るdoがcatch用のdoと共用できますね
だね
Avatar
omochimetaru 22-Oct-18 04:29 AM
↑そう書ければそれ自体は良さそうに感じるんだけどなあ
Avatar
tarunon 22-Oct-18 04:30 AM
Javaはデストラクタでthrowsあるんでしたっけ
Avatar
omochimetaru 22-Oct-18 04:31 AM
If an uncaught exception is thrown during the finalization, the exception is ignored and finalization of that object terminates.
04:31
Possible Duplicate: method finalize and exceptions The garbage collector invokes finalize() method when an object is about to released from memory. What happens when an exception is raised in ...
Avatar
koher 22-Oct-18 04:31 AM
これってでもすごく難しいような・・・
struct Foo { var a: Any func bar(_ out: OutputStream) { a = out } func baz() { do { let stream = try OutputStream() bar(stream) } catch let error { // ここで stream が破棄されるか調べるのが大変 ... } } }
Avatar
omochimetaru 22-Oct-18 04:31 AM
自動的に無視されるようだ
Avatar
norio_nomura 22-Oct-18 04:31 AM
明示的に呼び出せないdeinitthrowsにするのは無茶な気がする。
Avatar
omochimetaru 22-Oct-18 04:31 AM
Ownershipで endScope<T>(T) が入ると明示的に呼び出せる・・・
04:32
endScopeに渡した変数はそのスコープでそれ以降使用できない。(初回代入をする前のletのような扱い
04:32
Any型が全部throwになっちゃうのか!w
Avatar
tarunon 22-Oct-18 04:33 AM
あー
Avatar
omochimetaru 22-Oct-18 04:33 AM
オシマイみがあるな
Avatar
tarunon 22-Oct-18 04:33 AM
それはそうなる、やばそう
Avatar
koher 22-Oct-18 04:34 AM
親の deinitthrows がついてないと子の deinitthrows つけられないし厳しそう
04:34
いや、それはそれでいいのか
Avatar
omochimetaru 22-Oct-18 04:34 AM
それ自体はコンパイラで保証できますね
04:34
そうなってなければ型エラー
Avatar
koher 22-Oct-18 04:34 AM
Java みたいにすべてのクラスが Object を継承してるわけじゃないから。
04:35
Any はクラスじゃないし。でも existential が破綻するのか。
Avatar
omochimetaru 22-Oct-18 04:35 AM
破綻するというかAnyとかExistentialとかスーパータイプ的なやつらは全部 deinit throws になっちゃいますね
Avatar
tarunon 22-Oct-18 04:35 AM
deinit throwsを格納するための型アノテーションが必要そう
Avatar
omochimetaru 22-Oct-18 04:36 AM
それか逆に、 Anyとそれとは別に Any<throwing deinit> みたいな型をわけるか。
Avatar
tarunon 22-Oct-18 04:36 AM
throws AnyはAnyのスーパータイプ (edited)
Avatar
omochimetaru 22-Oct-18 04:36 AM
throwing deinitな型はthrowing deinitなスーパータイプにしかアップキャストできない、とする。
Avatar
tarunon 22-Oct-18 04:37 AM
関数のthrowsと似た扱いなのかな
Avatar
norio_nomura 22-Oct-18 04:37 AM
deinit throwsが公開されてる型なのかチェックしないといけないとか、無理すぎる。
Avatar
tarunon 22-Oct-18 04:37 AM
endScopeがあるなら
04:38
明示的deinitを追加してそっちでやる方が健全ぽいけど
Avatar
koher 23-Oct-18 06:08 AM
@swift-4.2.4
func run(_ body: @escaping () -> Void) { body() } class Foo { var a: Int = 42 func bar() { run { a += 1 } } }
Avatar
swift42 BOT 23-Oct-18 06:08 AM
exit status: 1 with stderr:
<stdin>:9:13: error: reference to property 'a' in closure requires explicit 'self.' to make capture semantics explicit a += 1 ^ self.
Avatar
koher 23-Oct-18 06:08 AM
@swift-4.2.4 @swift-nightly
func run(_ body: @escaping () -> Void) { body() } class Foo { var a: Int = 42 func bar() { func incrementA() { a += 1 } run(incrementA) } }
Avatar
swift42 BOT 23-Oct-18 06:08 AM
no output
Avatar
swiftNightly BOT 23-Oct-18 06:08 AM
no output
Avatar
koher 23-Oct-18 06:09 AM
↑ってローカル関数の場合は self. いらないんですっけ?仕様?チェック漏れ?
Avatar
omochimetaru 23-Oct-18 06:09 AM
仕様です
06:09
{ } で書いたときと func で書いた時で self の暗黙キャプチャ挙動が変わる
🤔 1
06:10
funcのときも self 明記しようぜ ってスレも何度か立ってますよ
😀 1
Avatar
koher 23-Oct-18 06:10 AM
funcのときも self 明記しようぜ
メソッドでなく、メソッドの中のローカル func (↑の incrementA )について?
(edited)
Avatar
omochimetaru 23-Oct-18 06:11 AM
そうですね
👌 1
Avatar
koher 27-Oct-18 11:35 PM
↓こんなメソッド( write(to:) )あるの初めて知った。 @swift-4.2.4
var out = "" "abc".write(to: &out) "def".write(to: &out) print(out)
Avatar
swift42 BOT 27-Oct-18 11:36 PM
abcdef
Avatar
hironytic 28-Oct-18 02:59 AM
知りませんでした。 + 演算子と何が違うん?と思いましたが、 to: の先は TextOutputStream なんですね。
Avatar
koher 28-Oct-18 08:28 AM
しかも、 StringTextOutputStream というのがおもしろいです。
08:30
String は可変長配列のように末尾に効率的に文字列を追加できるので、文字列を書き出す対象になれるということですね。一方で、(値型なので)他の言語でよくあるイミュータブルな文字列インスタンスと同じような性質も持っていると。
08:36
Java の StringStringBuilderWriter を合わせたような感じの役割を果たしてる感じでしょうか。
👀 1
Avatar
Kuniwak 28-Oct-18 08:47 AM
dump(to:) も同じ感じですね。これが TextOutputStream な理由は、(1) 標準出力とかに吐き出す都合で直接吐けた方が楽 or (2) 単にでかいテキストの末尾追加が発生しやすいから、のどちらかだと思うんですが、多分 1 ? https://developer.apple.com/documentation/swift/1641218-dump# (edited)
Avatar
koher 30-Oct-18 03:23 PM
@Kuniwak 値型 String なことで stream 的な性質を併せ持つこともできたということじゃないでしょうか?できるならそうしたいけど参照型のイミュータブルな String ではできなかったという意味合いで。
15:23
@swift-4.2.4
func foo(_ x: UInt8) { print("UInt8: \(x)") } func foo(_ x: Int) { print("Int: \(x)") } foo(.max)
Avatar
swift42 BOT 30-Oct-18 03:23 PM
exit status: 1 with stderr:
<stdin>:10:6: error: ambiguous use of 'max' foo(.max) ^ Swift.UnsignedInteger:4:23: note: found this candidate public static var max: Self { get } ^ Swift.SignedInteger:4:23: note: found this candidate public static var max: Self { get } ^
Avatar
koher 30-Oct-18 03:24 PM
@swift-4.2.4
func foo(_ x: UInt8) { print("UInt8: \(x)") } func foo(_ x: Int) { print("Int: \(x)") } foo(.max - 1)
Avatar
swift42 BOT 30-Oct-18 03:24 PM
Int: 9223372036854775806
Avatar
koher 30-Oct-18 03:24 PM
1Int と推論されて、それによって .max の型が Int と推論され、 Int.max になってる?
15:25
.max じゃダメだけど .max - 1 だと OK なのが、おもしろいというかわかりにくいというか・・・
Avatar
t.ae 31-Oct-18 12:51 AM
リテラルについてはambiguityがないようになってるんですねぇ
Avatar
omochimetaru 31-Oct-18 12:54 AM
リテラルはLiteralConvertibleとは別に、デフォルト型が定まってるからかな
Avatar
t.ae 31-Oct-18 12:55 AM
@swiftbot
func foo(_ x: UInt8) { print("UInt8: \(x)") } func foo(_ x: UInt16) { print("Int: \(x)") } foo(.max+0)
🛠 1
Avatar
swiftbot BOT 31-Oct-18 12:55 AM
Author icon
t.ae
func foo(_ x: UInt8) { print("UInt8: \(x)") } func foo(_ x: UInt16) { print("Int: \(x)") } foo(.max+0)
Version:
swift-4.1.1-RELEASE
Output:
Error:
/usercode/main.swift:9:9: error: ambiguous use of operator '+' foo(.max+0) ^ Swift.UInt8:9:24: note: found this candidate public static func + (lhs: UInt8, rhs: UInt8) -> UInt8 ^ Swift.UInt16:9:24: note: found this candidate public static func + (lhs: UInt16, rhs: UInt16) -> UInt16 ^
Avatar
t.ae 31-Oct-18 12:55 AM
優先順位じゃなくてデフォルトIntが決まってるだけなんですね。
00:56
確かに自作の型とか入ってくると優先順位付けようがないですしね。
Avatar
koher 31-Oct-18 02:36 AM
ExpressibleBy...Literal があるから任意の型に任意のリテラルを設定できるけど、何も指定しなかった場合のデフォルトは決まってて、その関係で 1 の型が決定されて .max の型も推論されてると思われる。
02:38
@swift-4.2.4
let a = .max - 1 print(a) let b: UInt8 = .max - 1 print(b)
Avatar
swift42 BOT 31-Oct-18 02:38 AM
9223372036854775806 254
Avatar
koher 31-Oct-18 02:39 AM
↓はコンパイルエラー @swift-4.2.4
let a = .max
Avatar
swift42 BOT 31-Oct-18 02:39 AM
exit status: 1 with stderr:
<stdin>:2:10: error: reference to member 'max' cannot be resolved without a contextual type let a = .max ~^~~
Avatar
Kuniwak 31-Oct-18 03:17 AM
@Kuniwak 値型 String なことで stream 的な性質を併せ持つこともできたということじゃないでしょうか?できるならそうしたいけど参照型のイミュータブルな String ではできなかったという意味合いで。
む、ここの koher さんの意図がわかりませんでした。。。
Avatar
koher 31-Oct-18 03:36 AM
@Kuniwak 僕が @Kuniwak さんの言いたかったことをちゃんと理解してない気がしてきました。
dump(to:) も同じ感じですね。これが TextOutputStream な理由は、(1) 標準出力とかに吐き出す都合で直接吐けた方が楽 or (2) 単にでかいテキストの末尾追加が発生しやすいから、のどちらかだと思うんですが、多分 1 ?
この「これが TextOutputStream な理由」の前には「○○ではなく」が隠れている気がするんですが、「○○」は何でしょう? String ?標準出力?
Avatar
omochimetaru 31-Oct-18 03:40 AM
@swift-4.2.4 -Xfrontend -debug-constraints
func foo(_ x: UInt8) {} func foo(_ x: Int) {} foo(.max - 1)
Avatar
swift42 BOT 31-Oct-18 03:40 AM
stderr:
---Constraint solving for the expression at [<stdin>:6:1 - line:6:13]--- ---Initial constraints for the given expression--- (call_expr type='()' location=<stdin>:6:1 range=[<stdin>:6:1 - line:6:13] arg_labels=_: (overloaded_decl_ref_expr type='$T0' location=<stdin>:6:1 range=[<stdin>:6:1 - line:6:1] name=foo number_of_decls=2 function_ref=single decls=[ main.(file).foo@<stdin>:2:6, main.(file).foo@<stdin>:4:6]) (paren_expr type='($T6)' location=<stdin>:6:10 range=[<stdin>:6:4 - line:6:13] (binary_expr type='$T6' location=<stdin>:6:10 range=[<stdin>:6:5 - line:6:12] (overloaded_decl_ref_expr type='$T1' location=<stdin>:6:10 range=[<stdin>:6:10 - line:6:10] name=- number_of_decls=20 function_ref=unapplied decls=[ Swift.(file).Float.-, Swift.(file).Double.-, Swift.(file).Float80.-, Swift.(file).UInt8.-, Swift.(file).Int8.-, Swift.(file).UInt16.-, Swift.(file).Int16.-, Swift.(file).UInt32.-, Swift.(file).Int32.-, Swift.(file).UInt64.-, Swift.(file).Int64.-, Swift.(file).UInt.-, Swift.(file).Int.-, Swift.(file).FloatingPoint.-, Swift.(file).Numeric.-, Swift.(file).BinaryInteger.-, Swift.(file).Strideable.-, Swift.(file).Strideable.-, Swift.(file).Strideable.-, Swift.(file).Strideable.-]) (tuple_expr implicit type='($T4, $T5)' location=<stdin>:6:5 range=[<stdin>:6:5 - line:6:12] (unresolved_member_expr type='$T4' location=<stdin>:6:6 range=[<stdin>:6:5 - line:6:6] name='max' arg_labels=') (integer_literal_expr type='$T5' location=<stdin>:6:12 range=[<stdin>:6:12 - line:6:12] value=1))))) Score: 0 0 0 0 0 0 0 0 0 0 0 Type Variables: $T0 [lvalue allowed] subtype_of_existential involves_type_vars bindings={} @ locator@0x68fcd10 [OverloadedDeclRef@<stdin>:6:1] $T1 [lvalue allowed] subtype_of_existential involves_type_vars bindings={} @ locator@0x68fce60 [Ove
Avatar
omochimetaru 31-Oct-18 03:41 AM
--- Solution #0 --- Fixed score: 0 0 0 0 0 1 0 0 0 0 0 Type variables: $T1 as (UInt8, UInt8) -> UInt8 @ locator@0x68fce60 [OverloadedDeclRef@<stdin>:6:10] --- Solution #1 --- Fixed score: 0 0 0 0 0 0 0 0 0 0 0 Type variables: $T1 as (Int, Int) -> Int @ locator@0x68fce60 [OverloadedDeclRef@<stdin>:6:10]
03:44
enum ScoreKind { // These values are used as indices into a Score value. /// A fix needs to be applied to the source. SK_Fix, /// A reference to an @unavailable declaration. SK_Unavailable, /// An implicit force of an implicitly unwrapped optional value. SK_ForceUnchecked, /// A user-defined conversion. SK_UserConversion, /// A non-trivial function conversion. SK_FunctionConversion, /// A literal expression bound to a non-default literal type. SK_NonDefaultLiteral, /// An implicit upcast conversion between collection types. SK_CollectionUpcastConversion, /// A value-to-optional conversion. SK_ValueToOptional, /// A conversion to an empty existential type ('Any' or '{}'). SK_EmptyExistentialConversion, /// A key path application subscript. SK_KeyPathSubscript, /// A conversion from a string, array, or inout to a pointer. SK_ValueToPointerConversion, SK_LastScoreKind = SK_ValueToPointerConversion, };
03:44
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
03:44
スコアの6つ目の要素が NonDefaultLiteral だから
03:45
UInt8が選択された場合、これが1点になって、Intの0点が優先、っぽい。
Avatar
Kuniwak 31-Oct-18 09:26 AM
@koher
この「これが TextOutputStream な理由」の前には「○○ではなく」が隠れている気がするんですが、「○○」は何でしょう? String ?標準出力?
「戻り値 string ではなく」引数 inout TextOutputStream な理由みたいな感じですね
(edited)
Avatar
koher 31-Oct-18 09:30 AM
なるほど
Avatar
omochimetaru 08-Nov-18 07:02 AM
@hironytic
そういえば、Existentialがそれ自身のプロトコルには準拠しない、っていうやつの理由は何なんでしょう?
@ukitaka によると https://qiita.com/ukitaka/items/8bcff4348c79d820ba32 Existential は { ∃X where X: Animal, X } の事で 、その考え方ではプロトコルに準拠してるのはXであって Existential ではないから、という説明になるらしいですけど、僕はよくわかってないです。
iOSのDiscordで定期的にあがる話題として「protocol型の値がそのprotocol自身にconformしていないのはなぜ?」というものがあります。 例えば以下のようなコードです。 ```swift protocol An...
Avatar
hironytic 08-Nov-18 07:30 AM
そうですよね。その @ukitaka さんのやつは何度か読んだことがあって、そちらの理由としては「Existential とはそういうものだから」ってことになるんだと思うんですけど、SwiftはExistentialを言語の裏側に隠していて、まるでプロトコルが型であるかのように、メソッドを呼び出したら暗黙的にOpening existentialを行うという振る舞いをさせているわけで。それなら、さらにExistentialがプロトコルに準拠してるように振る舞わせた方がわかりやすくはなりますよね。
07:30
まあ、そうなったものをExistentialと呼んでいいのかどうかは知りませんが。
Avatar
omochimetaru 08-Nov-18 07:34 AM
そうですね。パッケージングと unpackage + メソッド呼び出し に関しては Existential ではないかのように暗黙に実現されているのであれば、現状は中途半端で、その方針で突き進めたら普通に準拠してる扱いで良さそうだし、便利なのでは?と思います。
Avatar
koher 08-Nov-18 07:37 AM
Existential の乱用が始まりそうな気も。
Avatar
omochimetaru 08-Nov-18 07:37 AM
ExistentialにExistentialが埋め込めちゃう問題もありますね
Avatar
hironytic 08-Nov-18 07:41 AM
ExistentialにExistentialが埋め込まれるパターンってできるんですかね?Existentialとしては見せてないから裏側で埋め込まずにうまくできそうな気もしますが。あくまで気がするだけでよくわかってません。
Avatar
omochimetaru 08-Nov-18 07:42 AM
func package<T: P>(_ t: T) -> P { return t } let p0: P = package(Cat()) let p1: P = package(p0)
こうすると入れ子になると思います。実装上それを避ける事はできそうですが、変なケースが生じないかとか、入れ子にならないことが正しいのか?とか気になります。
(edited)
Avatar
koher 08-Nov-18 07:43 AM
@swift-4.2.4
protocol P { var x: Any { get set } } struct S: P { var x: Any } let p: P = S(x: 42)
Avatar
swift42 BOT 08-Nov-18 07:43 AM
no output
Avatar
koher 08-Nov-18 07:43 AM
Any も existential だからすでに埋め込めるのでは?
Avatar
omochimetaru 08-Nov-18 07:44 AM
AnyをAnyで受けるときはprotocolで受けてないですよね
Avatar
koher 08-Nov-18 07:45 AM
↓でもいいか。 @swift-4.2.4
protocol Q {} protocol P { var x: Q { get set } } struct T: Q {} struct S: P { var x: Q } let p: P = S(x: T())
(edited)
Avatar
omochimetaru 08-Nov-18 07:45 AM
ExistentialのAnyをExistentialのAnyに代入しているだけ
Avatar
swift42 BOT 08-Nov-18 07:45 AM
no output
Avatar
koher 08-Nov-18 07:46 AM
埋め込むの言いたいことがわかってないのかも。↑の P には Q が埋め込まれてない?
Avatar
hironytic 08-Nov-18 07:46 AM
@omochimetaru Existentialを作るところで埋め込まずにコピーするとかできそうな気はしますが、本当に大丈夫かというのとflattenしていいのかというのは確かによくわからないですね。 (edited)
Avatar
omochimetaru 08-Nov-18 07:46 AM
埋め込むというのは <T> T: P のときに T を P にアップキャストする挙動のことです
07:47
プロパティでhas-aにするという事ではないです
Avatar
hironytic 08-Nov-18 07:47 AM
あ、 has-a のことかと思ってた。
Avatar
koher 08-Nov-18 07:48 AM
それって Existential がプロトコルに準拠するのと同じことを言ってない?? (edited)
Avatar
omochimetaru 08-Nov-18 07:49 AM
func package<T: P>(_ t: T) -> P { // ここでPのExistentialが作られて、Tはその中に保持される return t } // これは普通 let p0: P = package(Cat()) // このとき、callee側ではPではなくT: Pとして来るので、 // 同じように T を保持する P が作られて、 結果的に P { P { T } } になりそう。 let p1: P = package(p0)
Avatar
hironytic 08-Nov-18 07:50 AM
その意味で捉えてましたが、これは has-a ではない?
07:50
あ、「プロパティで」か。
Avatar
omochimetaru 08-Nov-18 07:50 AM
has-a ではない、といったのは、koherの書いた
protocol P { var x: Q { get set } }
↑ここを見て言いました
07:50
Existentialの仕組み自体は has-a 的ですね。
Avatar
koher 08-Nov-18 07:51 AM
そのときは t を使おうとした瞬間に open されてもう一度 existential container に包まれるんじゃないのかなぁ。
Avatar
omochimetaru 08-Nov-18 07:51 AM
tの型は P ではなく <T: P> だから、 open するコードが吐けなそう。
07:52
一回目の呼び出しと同じ関数なので。
07:52
P である Cat や、 P である Dog と同様に、 P である P としか見えない
Avatar
koher 08-Nov-18 07:52 AM
PT として扱おうとした時点で、暗黙的に open するんじゃない?
Avatar
omochimetaru 08-Nov-18 07:52 AM
let p1: P = package(p0 /* あ〜ここか */)
Avatar
koher 08-Nov-18 07:53 AM
func foo<T: P>(_ t: T) { t.foo() }
Avatar
omochimetaru 08-Nov-18 07:53 AM
たしかにそれなら。
Avatar
koher 08-Nov-18 07:53 AM
そっちじゃなくてコール側かと思ってたけど、
Avatar
omochimetaru 08-Nov-18 07:53 AM
つまり実行時に もし func package の中で print(type(of: )) したときは、 Cat が得られるってことですね。
Avatar
koher 08-Nov-18 07:53 AM
↑のようなコードを考えたら TP でも動かないといけないわけで
07:54
選択肢は open してから渡すか
07:54
Existential でも普通のインスタンスのように振る舞わせる何かが間に挟まるか
07:54
どっちかかなぁと思って、後者をイメージしてた。けど前者の方が素直かも。
Avatar
omochimetaru 08-Nov-18 07:58 AM
Existential でも普通のインスタンスのように振る舞わせる何かが間に挟まるか
もしこの場合は、外側から見て区別がつかないので、入れ子になってしまいそう。
Avatar
koher 08-Nov-18 08:40 AM
たしかにそうかも。
Avatar
koher 08-Nov-18 04:18 PM
@swift-4.2.4
let b = Bool.random() switch b { case true: print("T") case false: print("F") }
Avatar
swift42 BOT 08-Nov-18 04:18 PM
F
Avatar
koher 08-Nov-18 04:18 PM
↑が網羅性チェック通るのってなぜ? Bool だけ特殊?
Avatar
koher 09-Nov-18 01:20 AM
お、 @dynamicCallable の PR が作り直されていて [WIP] も外れてる。 https://github.com/apple/swift/pull/20305
This PR introduces the @dynamicCallable attribute, which enables nominal types to be "callable" via a simple syntactic sugar. This is the implementation of SE-0216. Read the proposal for ...
Avatar
omochimetaru 09-Nov-18 01:24 AM
Swift5 branchingに間に合いそうですね
Avatar
koher 09-Nov-18 01:25 AM
あと一週間。ギリギリだなぁ。マージされてほしい。
Avatar
rintaro 09-Nov-18 03:17 AM
AnyHashable の実装みてたんですが、 associatedtype無しの Self 制約だけであれば protocol で type erasure 書けるんですねー。
03:17
@swift-4.2.4
protocol Equattable { func equaals(to other: Self) -> Bool } extension Int: Equattable { func equaals(to other: Int) -> Bool { return self == other } } extension String: Equattable { func equaals(to other: String) -> Bool { return self == other } } protocol _AnyEquattableBox { func _unbox<T: Equattable>() -> T? func _equaals(to box: _AnyEquattableBox) -> Bool? } struct _ConcreteEquattableBox<Base: Equattable> : _AnyEquattableBox { var _baseEquattable: Base init(_ base: Base) { self._baseEquattable = base } func _unbox<T: Equattable>() -> T? { return (self as _AnyEquattableBox as? _ConcreteEquattableBox<T>)?._baseEquattable } func _equaals(to box: _AnyEquattableBox) -> Bool? { guard let rhs: Base = box._unbox() else { return nil } return _baseEquattable.equaals(to: rhs) } } struct AnyEquattable: Equattable { var _box: _AnyEquattableBox init<E: Equattable>(_ base: E) { _box = _ConcreteEquattableBox(base) } func equaals(to rhs: AnyEquattable) -> Bool { return _box._equaals(to: rhs._box) ?? false } } let intVal1 = AnyEquattable(1) let intVal2 = AnyEquattable(1) let intVal3 = AnyEquattable(2) let strVal = AnyEquattable("test") assert(intVal1.equaals(to: intVal2)) assert(!intVal1.equaals(to: intVal3)) assert(!intVal1.equaals(to: strVal))
Avatar
swift42 BOT 09-Nov-18 03:17 AM
no output
Avatar
omochimetaru 09-Nov-18 03:19 AM
!!ww
03:19
classの継承関係にしてfatalErrorを書かないといけないところが、 protocol + struct になっているのか?
03:19
TypeErasure 新方式だ
Avatar
koher 09-Nov-18 03:20 AM
# Type erasure swift では protocol を使うのが人気です。ある protocol を満たす複数の型があるとき、それらのどれでも代入できる互換性のある型が欲しくなることがあります。そのような型を type ...
Avatar
omochimetaru 09-Nov-18 03:23 AM
なるほど・・・ Existentialが使える場合→associatedtypeがある場合→さらにSelfも使っている場合 っていう風にその記事を書いたときは整理したけど
03:23
associatedtypeが無いけどSelfを使っている場合 というのが存在して
03:23
その場合にはそのパターンが使えるんですね。
Avatar
rintaro 09-Nov-18 03:26 AM
https://github.com/apple/swift/blob/e7dd1c17b23d3080af490cd69c535d267052af52/stdlib/public/core/AnyHashable.swift#L59-L63 これの意味がわからない。_canonicalBox というのが何故必要なのか?
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
Avatar
omochimetaru 09-Nov-18 03:30 AM
AnyHashable has numerous edge cases where two AnyHashable values compare equal but produce different hashes. This breaks Set and Dictionary invariants and can cause unexpected behavior and/or traps...
Avatar
rintaro 09-Nov-18 03:30 AM
https://github.com/apple/swift/blob/e7dd1c17b23d3080af490cd69c535d267052af52/stdlib/public/core/Dictionary.swift#L1670 などで、concrete type ごとにカスタマイズしているからでした。
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
Avatar
omochimetaru 09-Nov-18 03:30 AM
ちょうどたどり着きつつ会った
03:33
起点となるのは、AnyHashable.init冒頭の (base as? _HasCustomAnyHashableRepresentation)?._toCustomAnyHashable() ですね
03:33
これでAnyHashableの中で捕まえておくboxを型固有のboxにできる穴が空いている
03:35
let a = (42 as Int as AnyHashable) let b = (42 as NSNumber as AnyHashable) let c = (42 as Double as AnyHashable) a == b // true b == c // true a == c // was false(!), now true
03:35
AnyHashable経由だと Int(42) == Double(42) なの・・・?
Avatar
rintaro 09-Nov-18 03:36 AM
むむ。
Avatar
koher 09-Nov-18 03:36 AM
@swift-4.2.4
print(AnyHashable(42 as Int) == AnyHashable(42.0 as Double))
Avatar
swift42 BOT 09-Nov-18 03:36 AM
true
Avatar
omochimetaru 09-Nov-18 03:36 AM
↑はそのcanonicalBoxが追加されたコミットのコミットメッセージ。
03:37
@swift-4.1.3
print(AnyHashable(42 as Int) == AnyHashable(42.0 as Double))
Avatar
swift41 BOT 09-Nov-18 03:37 AM
false
😨 1
Avatar
omochimetaru 09-Nov-18 03:37 AM
ワーオw
Avatar
koher 09-Nov-18 03:37 AM
w
Avatar
tarunon 09-Nov-18 04:24 AM
41の方が正しそう
Avatar
omochimetaru 09-Nov-18 04:24 AM
@tarunon その前の話題の新しいErasureも見て
Avatar
tarunon 09-Nov-18 04:28 AM
いまみてる
Avatar
tarunon 09-Nov-18 05:15 AM
サブクラス問題を解決できなさそう
Avatar
omochimetaru 09-Nov-18 05:24 AM
サブクラス問題って何?
Avatar
tarunon 09-Nov-18 05:25 AM
@swift-4.2.4
protocol AnyEquatableBox { func _unbox<T: Equatable>() -> T? func _equals(to box: AnyEquatableBox) -> Bool? } struct ConcreteEquatableBox<Base: Equatable>: AnyEquatableBox { var base: Base init(_ base: Base) { self.base = base } func _unbox<T>() -> T? where T : Equatable { return ((self as AnyEquatableBox) as? ConcreteEquatableBox<T>)?.base } func _equals(to box: AnyEquatableBox) -> Bool? { guard let rhs: Base = box._unbox() else { return nil } return base == rhs } } struct AnyEquatable: Equatable { var box: AnyEquatableBox init<E>(_ base: E) where E: Equatable { box = ConcreteEquatableBox(base) } static func == (lhs: AnyEquatable, rhs: AnyEquatable) -> Bool { return lhs.box._equals(to: rhs.box) ?? false } } class Animal: Equatable { static func == (lhs: Animal, rhs: Animal) -> Bool { return lhs === rhs } } class Cat: Animal { } let cat1 = Cat() let cat2 = cat1 as Animal assert(AnyEquatable(cat1) == AnyEquatable(cat2))
Avatar
swift42 BOT 09-Nov-18 05:25 AM
exit status: 4 with stderr:
Assertion failed: : file <stdin>, line 46 Current stack trace: 0 libswiftCore.so 0x00007fde1b750fa0 _swift_stdlib_reportFatalErrorInFile + 215 1 libswiftCore.so 0x00007fde1b4a95c1 <unavailable> + 1504705 2 libswiftCore.so 0x00007fde1b6e60c2 <unavailable> + 3850434 3 libswiftCore.so 0x00007fde1b4a8d0a <unavailable> + 1502474 4 libswiftCore.so 0x00007fde1b6e5f5c <unavailable> + 3850076 5 libswiftCore.so 0x00007fde1b4a8d0a <unavailable> + 1502474 6 libswiftCore.so 0x00007fde1b642a28 <unavailable> + 3181096 7 libswiftCore.so 0x00007fde1b4a85a9 <unavailable> + 1500585 9 swift 0x0000000001043efe <unavailable> + 12861182 10 swift 0x0000000001048022 <unavailable> + 12877858 11 swift 0x00000000004f8b42 <unavailable> + 1018690 12 swift 0x00000000004df0bb <unavailable> + 913595 13 swift 0x00000000004da3f0 <unavailable> + 893936 14 swift 0x000000000048a348 <unavailable> + 566088 15 libc.so.6 0x00007fde1e0f5740 __libc_start_main + 240 16 swift 0x0000000000488009 <unavailable> + 557065 #0 0x000000000410ac94 PrintStackTraceSignalHandler(void*) (/usr/bin/swift+0x410ac94) #1 0x0000000004108b22 llvm::sys::RunSignalHandlers() (/usr/bin/swift+0x4108b22) #2 0x000000000410ae42 SignalHandler(int) (/usr/bin/swift+0x410ae42) #3 0x00007fde1f9cb390 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x11390) #4 0x00007fde1b642a30 $Ss17_assertionFailure__4file4line5flagss5NeverOs12StaticStringV_SSAHSus6UInt32VtFTf4nxnnn_n (/usr/lib/swift/linux/libswiftCore.so+0x308a30) #5 0x00007fde1b4a85a9 (/usr/lib/swift/linux/libswiftCore.so+0x16e5a9) #6 0x0000
Avatar
tarunon 09-Nov-18 05:26 AM
これってBox式もそうだっけ
Avatar
omochimetaru 09-Nov-18 05:32 AM
同じ気がする クラッシュ回避のためにEquatableについてはboxの型が同じかどうかをチェックしても良さそう
Avatar
tarunon 09-Nov-18 05:35 AM
しかし生成時に型が焼き込まれてしまうのでうまく動かすのは難しそうだなぁ
Avatar
omochimetaru 09-Nov-18 05:38 AM
ああ読み違えてた CatとDogじゃなくてCatとAnimalか
Avatar
norio_nomura 09-Nov-18 05:43 AM
print(AnyHashable(42 as Int) == AnyHashable(42.0 as Double))の挙動は意図したものなのね。 https://github.com/apple/swift/pull/17396
AnyHashable has a few corner cases where it's not correctly conforming to Equatable and Hashable. This breaks Set and Dictionary invariants and can cause unexpected behavior and/or traps. This ...
Avatar
omochimetaru 09-Nov-18 06:04 AM
@swift-4.2.4
class Animal : Hashable { static func ==(a: Animal, b: Animal) -> Bool { return a === b } func hash(into hasher: inout Hasher) { hasher.combine(ObjectIdentifier(self)) } } class Cat : Animal {} class Dog : Animal {} let a = Cat() let b: Animal = a let c: Animal = Dog() print(AnyHashable(a) == AnyHashable(c), 3)
(edited)
Avatar
swift42 BOT 09-Nov-18 06:04 AM
false 3
(edited)
Avatar
omochimetaru 09-Nov-18 06:09 AM
@tarunon なんかAnyHashableはサブクラス問題大丈夫っぽい
Avatar
tarunon 09-Nov-18 06:09 AM
hashは型情報いらないからね
Avatar
omochimetaru 09-Nov-18 06:10 AM
Hashable is Equatableだよ
Avatar
tarunon 09-Nov-18 06:10 AM
だとすると、AnyHashableに包んで==比較すると
Avatar
omochimetaru 09-Nov-18 06:11 AM
AnyHashableに入れるためにはHashableに準拠させるためにstatic func ==とfunc hash(into:) の実装が必要
Avatar
tarunon 09-Nov-18 06:11 AM
hashは取れるけどequatabiltyは壊れてるのがAnyHashableという理解
06:12
boxに詰めたオブジェクトについて保証されないのでは
Avatar
omochimetaru 09-Nov-18 06:12 AM
仮にそうだったとしたらDictionaryのKeyやSetのElementとして使い物にならんけど・・・どういうこっちゃ
Avatar
norio_nomura 09-Nov-18 06:25 AM
AnyHashableを作るときに、どんな_AnyHashableBoxを使うかカスタマイズできる_HasCustomAnyHashableRepresentationってのがあって、元がDoubleでもInt64(exactly:)で表現可能なら、_IntegerAnyHashableBoxを使う仕組みになってる。 https://github.com/apple/swift/blob/master/stdlib/public/core/FloatingPointTypes.swift.gyb#L1820-L1831
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
👀 1
Avatar
omochimetaru 09-Nov-18 06:26 AM
exactlyの正しい使い方だ
Avatar
norio_nomura 09-Nov-18 06:27 AM
それによりAnyHashable(42 as Int) == AnyHashable(42.0 as Double)trueになる。
Avatar
omochimetaru 09-Nov-18 06:27 AM
じゃあその右辺値が評価された時点で、本当に同じ構成のオブジェクトになってるんですね
06:28
比較する時点でやるよりそのほうが処理も早そうだ
Avatar
norio_nomura 09-Nov-18 06:32 AM
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
06:38
_AnyHashableBoxinternalだから、stdlib外の型ではカスタマイズ出来ないな。
Avatar
rintaro 09-Nov-18 06:49 AM
@swift-4.2.4
protocol AnyEquatableBox { func _unbox<T: Equatable>() -> T? func _equals(to box: AnyEquatableBox) -> Bool? } struct ConcreteEquatableBox<Base: Equatable>: AnyEquatableBox { var base: Base init(_ base: Base) { self.base = base } func _unbox<T: Equatable>() -> T? { return self.base as? T } func _equals(to box: AnyEquatableBox) -> Bool? { guard let rhs: Base = box._unbox() else { return nil } return base == rhs } } struct AnyEquatable: Equatable { var box: AnyEquatableBox init<E>(_ base: E) where E: Equatable { box = ConcreteEquatableBox(base) } static func == (lhs: AnyEquatable, rhs: AnyEquatable) -> Bool { return lhs.box._equals(to: rhs.box) ?? false } } class Animal: Equatable { static func == (lhs: Animal, rhs: Animal) -> Bool { return lhs === rhs } } class Cat : Animal {} class Dog : Animal {} let a = Cat() let b: Animal = a let c: Animal = Dog() assert(AnyEquatable(a) == AnyEquatable(b)) assert(AnyEquatable(a) != AnyEquatable(c)) assert(AnyEquatable(b) == AnyEquatable(a)) assert(AnyEquatable(b) != AnyEquatable(c)) assert(AnyEquatable(c) != AnyEquatable(a)) assert(AnyEquatable(c) != AnyEquatable(b))
Avatar
swift42 BOT 09-Nov-18 06:49 AM
no output
Avatar
rintaro 09-Nov-18 06:50 AM
_unbox を シンブルな conditional cast に変えただけ。
Avatar
omochimetaru 09-Nov-18 06:53 AM
lhsがConcreteEquatableBox<Cat> の場合は、box._unbox()が T == Cat で呼び出されて、内部で as? Cat、 Cat.== が呼ばれる rhsがConcreteEquatableBox<Animal> の場合は、 box._unbox() が T == Animal で呼び出されて、内部で as? Animal、 Animal.== が呼ばれる か
06:54
Cat.== と Animal.== の反射律は Cat と Animal の実装が責任を持ってるからおかしなことはナシと
06:54
そっかそれだけか
Avatar
norio_nomura 09-Nov-18 07:27 AM
それだと_ObjectiveCBridgeableの影響を受けそう。
Avatar
tarunon 09-Nov-18 12:34 PM
@rintaro ちゃんとできてる!ありがとうございます ところでこのパターン、シンプルなBoolを返す場合はいいけど、そこそこ込み入ったオブジェクトを返す場合は使えなさそうですね
Avatar
koher 14-Nov-18 03:58 AM
この前の↓だけど、このロジックでいけば JSONDecoder.decode とかは throws じゃなくて -> Result<...> であるべきということになりそうだけどどうだろう?
I think throws and Result can be seen as addressing different corners of the design space. As the rationale describes, throws was designed for systemic errors, which tend to have a large distance between error source and error handler, so source and handler end up needing to be rather loosely coupled, which was a motivator for the exception-like propagation and lack of specific typing in the current throws feature. Result on the other hand is great for conditions that are intended to be immediately handled by the caller, for which being an regular return value with a more specific failure type is in fact the more convenient representation.
https://forums.swift.org/t/adding-result-ii-unconstrained-boogaloo/17128/18
+1 to an unconstrained, two-argument Result type. Referring back to @John_McCall's original error handling rationale, I think throws and Result can be seen as addressing different corners of the design space. As the rationale describes, throws was designed for systemic errors...
04:04
I/O エラーやネットワークエラーみたいなのを "systemic errors" と呼んでいるとすると、それらを Recoverable Error として throws で扱うのに対して、 JSON のデコードの失敗はもっと確定的な処理で、 "an regular return value with a more specific failure type" に適しているように感じる。一種の Simple Domain Error になる?
Avatar
omochimetaru 14-Nov-18 04:15 AM
これはそんな気がします
04:16
throwsはエラーの原因とハンドラに距離があるときに適してて
04:17
一方、JSONのデコードにおけるエラーは JSONのデータ構造と値だけにほぼ依存してて
04:17
どこがどうおかしいとかキーパスで知りたいし
04:18
JSONDecodeError みたいな型付きで戻ってきたら便利だと思う
04:19
でも実際のところアプリケーションでそれによってハンドルすることがほぼないから、微妙だな
04:19
ログがdumpできて、ユーザには「通信エラー」とだけ出しとけばいい、みたいなやつだから、型はいらないっちゃいらない
Avatar
koher 14-Nov-18 04:48 AM
そうすると、↑のロジックを正当化して Result が追加されると、既存 API を変更するか、もしくは言語の期待する使い分けと異なるデザインの API が放置されるかという状況になって、どっちになっても結構辛そうな気がする。
04:49
そういう意見を投げたいところだけど、レビュー期間が終わってしまった。
Avatar
omochimetaru 14-Nov-18 05:05 AM
その場合、既存APIを変更するのが正しい道だと思います
05:05
それで過去に引っ張られたら言語の進化がそこで止まってしまう。
Avatar
koher 14-Nov-18 05:06 AM
既存 API 変更できればいいけど、できないんじゃないかなぁ。
05:07
String(data:using:) とかも Resultreturn すべきってことになるよね。
Avatar
omochimetaru 14-Nov-18 05:07 AM
なるほど
Avatar
koher 14-Nov-18 05:08 AM
あと、ユーザビリティの問題として、↓とかが throws じゃなくて Result になったらずいぶん使いづらいと思う。 https://developer.apple.com/documentation/swift/keyeddecodingcontainer/2921334-decode (edited)
Avatar
Kishikawa Katsumi 14-Nov-18 05:09 AM
Resultを返す別のAPIを追加したらよくて、Decodableの場合は別のJSONDecoderを追加したらいい。
05:09
String(data:using:) の例も別のメソッド/イニシャライザでOK
Avatar
koher 14-Nov-18 05:10 AM
@Kishikawa Katsumi それだと "addressing different corners of the design space" ということにならなくないですか?
05:10
Joe Groff は "systrmic error" に throws を使うべきと言っていて
05:11
両方用意しておけば良いということになれば、 API 設計がぐちゃぐちゃになりそうに思います。
Avatar
Kishikawa Katsumi 14-Nov-18 05:12 AM
Resultsとthrowsはそれぞれ別の問題を、、、というは多分同意で、 それでJSONDecoderも一部のエラーはResultの方が良いというのも私は多分同意
Avatar
koher 14-Nov-18 05:12 AM
僕は多くのケースで最適なものを用意しておいて、それが適さないケースでは適宜変換して使う(簡単に変換できる)というのが望ましいと思います。
Avatar
Kishikawa Katsumi 14-Nov-18 05:12 AM
ただ既存のAPIをどうするという問題はあってそれは別問題で、
その場合、既存APIを変更するのが正しい道だと思います それで過去に引っ張られたら言語の進化がそこで止まってしまう。
Avatar
koher 14-Nov-18 05:13 AM
なるほど。「既存のAPIをどうするという問題」への対処として、ということですね。
Avatar
Kishikawa Katsumi 14-Nov-18 05:13 AM
^ これに対する応答として、一般的な解は一時的に共存しつつ、どちらかを漸進的にDeprecateしていくようにすべき、
05:13
という意見です。
🙂 1
Avatar
omochimetaru 14-Nov-18 05:13 AM
なるほど。
Avatar
Kishikawa Katsumi 14-Nov-18 05:14 AM
それで過去に引っ張られたら言語の進化がそこで止まってしまう。
^ 実はこれには完全同意なんですけど、もはやそれをしてはいけないという意見も同時に私の中にある。
Avatar
koher 14-Nov-18 05:14 AM
「もはやそれをしてはいけない」の「それ」は「進化」ですか?
05:15
それとも「止ま」ること?
Avatar
Kishikawa Katsumi 14-Nov-18 05:15 AM
いや、破壊的な変更を伴う、です。
05:15
進化は必要でどこかで古いものを捨てる、破壊するは必要なんですけど、
💪 1
Avatar
koher 14-Nov-18 05:16 AM
(破壊的な変更を伴う)「進化」ということですね。
Avatar
Kishikawa Katsumi 14-Nov-18 05:16 AM
JSONのAPIだけに限るとしても、フルスクラッチみたいなことをするのは良くない、と思いますね。
05:17
これは個人的な意見ですけど、Resultを入れると既存のサードパーティ製のResultを使ったコードが死ぬ、というのは現段階では気にしなくて良いと思います。この感覚の違いを言語化するのは難しいんですけど。
Avatar
koher 14-Nov-18 05:18 AM
難しいところですね。現実的にはある程度長期に( 5 年とか)互換性を保つことを保証しつつ、その保証期間を超えるときにまとめて破壊して進化とかでしょうねー。
05:18
本当はそれがメジャーバージョンアップな気がしますが、 Swift のメジャーバージョンは軽く扱われてるので・・・。
05:19
Resultを入れると既存のサードパーティ製のResultを使ったコードが死ぬ、というのは現段階では気にしなくて良いと思います。
これは僕も気にしなくて良いと思います。
05:20
ただ、今の Swift はまだその段階(互換性を気にすべき)に達していないと思っていて、
05:21
Swift のバージョンの前には 0. を付けた感じだと思うんですよね。
05:21
今は 0.4.2 みたいな。
05:21
で、これを 1.0 にした段階で 1.x の間は後方互換を保ち、そのスパンが 5 年くらいがいいのかなと。
05:22
サポート期間はもっと長くてもいいのかも。
Avatar
Kishikawa Katsumi 14-Nov-18 06:11 AM
ただ、今の Swift はまだその段階(互換性を気にすべき)に達していないと思っていて
これはまあ実際そうだと思いますが、 これは自然に訪れるものではなくて、理想を求めたらいつまでも終わらないので、 公開して使ってもらう、そして公開した以上は互換性を(ある程度)守りながら進化させていくっていうのは必要かなと。
Avatar
koher 14-Nov-18 06:24 AM
そういう意味では、現状は「公開した以上は互換性を(ある程度)守りながら進化させていく」になってそうですね。現状で目に見えている問題( async/awaitactor, typed throws など)が片付くまではそういう形を続けて、それらが片付いたらもう少しきっちり互換性を守るべきなのかなぁと思います。
Avatar
koher 14-Nov-18 06:43 AM
throws は "systemic error" に用いるべきというのもちょっと懐疑的で、↓のようになるのが望ましいと思えない・・・。結局 Resultthrows のための get だらけ。
extension Foo: Decodable { init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) self.a = try container.decode(Int.self, forKey: .a).get() self.b = try container.decode(String.self, forKey: .b).get() } }
06:44
しかもinitResultreturn できないから throws にせざるを得ない。
Avatar
omochimetaru 14-Nov-18 06:44 AM
init(from decoder:) が throws じゃなくて JSONError を返す Result になる気がする。
06:44
initだからできないというのはそうですね。
06:44
てか、その目的で置換するなら先にtyped throws が必要なのでは。
Avatar
koher 14-Nov-18 06:45 AM
init? のようなものを導入するなら、昔僕が提案してたみたいな | を導入して、 T|EResult<T, E> のシュガーにした上で、 init| とか導入しないと・・・。
Avatar
omochimetaru 14-Nov-18 06:46 AM
init(from decoder: ) throws(JSONError) とか。
Avatar
koher 14-Nov-18 06:46 AM
それだと typed throws と Resultreturn の両方を扱えないよ。
Avatar
omochimetaru 14-Nov-18 06:47 AM
returnの両方?
Avatar
koher 14-Nov-18 06:48 AM
initthrow する場合と Resultreturn する場合の両方を扱えないといけないはず。
Avatar
omochimetaru 14-Nov-18 06:48 AM
あ、そこで区切るのか。
Avatar
koher 14-Nov-18 06:49 AM
String.init(data:using:)Resultreturn したいけど、 Database.init(path:)throw したいはず。
Avatar
omochimetaru 14-Nov-18 06:50 AM
ふむ throwsと -> Result の扱いを分けないといけないのか
Avatar
koher 14-Nov-18 06:50 AM
正直、適切に使い分けられると思えないので、コミュニティで二つのスタイルが混在してコード書きづらくなりそう。
Avatar
omochimetaru 14-Nov-18 06:52 AM
ユーザ側で取り扱いたいときだけ Result { try hoge() } で Result化すればいいような気がしてきたな
Avatar
koher 14-Nov-18 06:52 AM
多分本当に Result が必要なのって、 async/await に対する Future みたいなもので、局所的にしかたなく使うものであって、 API に現れる種類のものじゃないと思うんよね。
06:54
↑を init じゃなくて Resultreturn するメソッドとすると↓になる。
extension Foo: Decodable { static func from(_ decoder: Decoder) -> Result<Foo, DecodeError> { return Result { let container = try decoder.container(keyedBy: CodingKeys.self) let a = try container.decode(Int.self, forKey: .a).get() let b = try container.decode(String.self, forKey: .b).get() return Foo(a: a, b: b) } } }
06:54
何もうれしくない。
06:54
もし間に getthrows への変換を挟まないともっと悲惨になる。
06:56
extension Foo: Decodable { static func from(_ decoder: Decoder) -> Result<Foo, DecodeError> { let container = try decoder.container(keyedBy: CodingKeys.self) let a: A switch container.decode(Int.self, forKey: .a) { case .success(let value): a = value case .failure(let error): return .failure(error) } let b: B switch container.decode(Int.self, forKey: .b) { case .success(let value): b = value case .failure(let error): return .failure(error) } return .success(Foo(a: a, b: b)) } }
(edited)
06:58
decodeResultreturn するようにしても何がうれしいのかさっぱりだし、 decodethrows のままにするならどこで Result 使うの?って感じ。
06:58
すごく限定的な用途しかなさそう。
07:02
それか Functional な道を開いて↓になる。さすがにこれはない。
extension Foo: Decodable { static func from(_ decoder: Decoder) -> Result<Foo, DecodeError> { return decoder.container(keyedBy: CodingKeys.self).flatMap { container in return curry(Foo.init) <^> container.decode(Int.self, forKey: .a) <*> container.decode(String.self, forKey: .b) } } }
Avatar
koher 14-Nov-18 08:49 AM
John McCall の↓はより限定的な Result の利用を推奨してる?
I want to clarify that I favor adding Result only to address situations where manual propagation is necessary. Manual propagation will always occasionally be useful; adding async/await (or whatever we end up doing) will surely eliminate most of the most common situations, but they'll still exist, e.g. when using futures (which are the equivalent of manual propagation for async/await and accordingly trigger similar requirements). I will continue to recommend against using Result as an alternative mechanism for ordinary propagation of errors, although I have no doubt that some people will insist on doing so; and I continue to believe that using a different error type than Error is generally misguided for the same reason it's generally misguided with ordinary error-handling. I also worry that the ergonomics of this type are significantly hurt by the attempt to support typed errors and (especially) non-Error-conforming errors.
https://forums.swift.org/t/se-0235-add-result-to-the-standard-library/17752/129
I want to clarify that I favor adding Result only to address situations where manual propagation is necessary. Manual propagation will always occasionally be useful; adding async/await (or whatever we end up doing) will surely eliminate most of the most common situations, bu...
Avatar
koher 16-Nov-18 05:38 PM
レビュー期間終わってたけど気になったので書いてみた。 https://forums.swift.org/t/se-0235-add-result-to-the-standard-library/17752/183
Although the review period is over, please let me leave my comment. I have been thinking about it for days. If I correctly understood what you intended in the comment below you linked, it seems to suggest that JSONDecoder.decode(_:from:) returns Results instead of throwing...
Avatar
norio_nomura 28-Nov-18 11:33 PM
SE-0235: Add Result to the Standard Library has been revised and is now open for review through Sunday, December 2nd. Based on the first round of feedback, the core team agrees that this feature is worth adding to Swift, and we are now looking for feedback on our proposed re...
23:35
https://github.com/apple/swift-evolution/commit/db086de27804f6103ab8cde8801d41eb67edca38
-public enum Result<Value, Error> { - case success(Value), failure(Error) +public enum Result<Value, Error: Swift.Error> { + case value(Value), error(Error) }
(edited)
Revise SE-0235 with core team feedback and put it back in review
Avatar
omochimetaru 29-Nov-18 12:34 AM
Avatar
omochimetaru 29-Nov-18 12:46 AM
情報量が濃厚だ ちゃんと訳してみよう
Avatar
koher 29-Nov-18 01:27 AM
大分好みな感じになった。
01:28
変なメソッドが除去されて必要最小限でいい感じ。
01:28
Error: Swift.Error になったのもいいと思う。
01:30
Result 乱用は絶対に起こると思うけど、 Result 追加するなら考えられる限りほぼベストな実装だと思う。
Avatar
tarunon 29-Nov-18 02:16 AM
ErrorのExistentialがErrorのprotocolにconformするようになってしまったのだけモニョる、他のExistentialもそうならいいけど特別扱いはなぁ (edited)
Avatar
omochimetaru 29-Nov-18 02:20 AM
たしかに。
Avatar
koher 29-Nov-18 02:51 AM
書いた。結局、 JSONDecoder.decode(_:from:)Resultreturn するのがいいの?それともしないのがいいの?って聞いてみた。 https://forums.swift.org/t/revised-se-0235-add-result-to-the-standard-library/18371/26
I agree on the changes. In particular, it looks great to me that the Error type parameters is constrained to conform to Swift.Error, with self-conformance, and the Result type has minimum APIs. I want a guideline when to use the Result type. Opinions seems divided even in ...
Avatar
koher 29-Nov-18 03:05 AM
Lifting this restriction in general is out of scope for Swift 5, but it can be lifted specifically for Swift.Error, making it conform to itself. Making that change is part of this proposal.
↑なので、 Swift 5 ではやらないけど Swift 6 以降のどこかではやるつもりなんじゃないでしょうか?
Avatar
omochimetaru 29-Nov-18 03:07 AM
↑それレス何番ですか?
Avatar
rintaro 29-Nov-18 03:09 AM
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
👍 1
Avatar
omochimetaru 29-Nov-18 03:10 AM
あー、0235の提案書が、書き換えられてるのか。
Avatar
koher 29-Nov-18 03:12 AM
うん、実装(ってかインタフェース)も書かれてていい感じ。
@_frozen public enum Result<Value, Error: Swift.Error> { case value(Value) case error(Error) public func map<NewValue>( _ transform: (Value) -> NewValue ) -> Result<NewValue, Error> public func mapError<NewError>( _ transform: (Error) -> NewError ) -> Result<Value, NewError> public func flatMap<NewValue>( _ transform: (Value) -> Result<NewValue, Error> ) -> Result<NewValue, Error> public func flatMapError<NewError>( _ transform: (Error) -> Result<Value, NewError> ) -> Result<Value, NewError> public func unwrapped() throws -> Value } extension Result where Error == Swift.Error { @_transparent public init(catching body: () throws -> Value) } extension Result : Equatable where Value : Equatable, Error : Equatable { } extension Result : Hashable where Value : Hashable, Error : Hashable { }
Avatar
omochimetaru 29-Nov-18 03:14 AM
いきなりURLSEssionの例が
03:14
Errorの場合のURLResponseのことが消えてるような
Avatar
koher 29-Nov-18 03:14 AM
あー、なんか変な気がしたけど、元がどうだったけなと思って読み飛ばした。
03:15
Error: Swift:Error じゃできないことだった気がするから
03:15
ああ、そうか
03:15
Error の場合でも URLResponse を持ちたかったのか。
Avatar
omochimetaru 29-Nov-18 03:15 AM
URLSession.shared.dataTask(with: url) { (result: Result<(URLResponse, Data), (Error, URLResponse?)>) in // Type added for illustration purposes. switch result { case .success(let response): handleResponse(response.0, data: response.1) case .failure(let error): handleError(error) } }
03:15
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
03:16
古いコミットのときの当該箇所。
03:16
responseってプロパティを持ったエラー型にするのでもよいけど、いずれにせよResultのErrorパラメタがSwift.Errorで埋められているので、そうなってもいない。
Avatar
koher 29-Nov-18 03:17 AM
うん。消えてるね、これ。
03:18
まあ、 Error 型のプロパティでやるのが順当だろうけど、元が Obj-C で NSError だからなぁ。
Avatar
omochimetaru 29-Nov-18 03:18 AM
NSErrorのエラー型は
03:18
Domainに基づいてBridgeできるのでそこは大丈夫では。
03:18
CocoaErrorとかURLErrorとか。
Avatar
koher 29-Nov-18 03:19 AM
URLResponse をすでに持ってる型なの?
03:20
ブリッジできても URLRespose を持ってないのであれば解決しない気が。
Avatar
omochimetaru 29-Nov-18 03:20 AM
extension URLError { /// The URL which caused a load to fail. public var failingURL: URL? { get } /// The string for the URL which caused a load to fail. public var failureURLString: String? { get } /// The state of a failed SSL handshake. public var failureURLPeerTrust: SecTrust? { get } }
03:20
URLResponseは持ってないですね。
Avatar
koher 29-Nov-18 03:20 AM
じゃあ同等にはならないね・・・
03:20
ってかさ、
03:21
(result, response) を受け取るんでいいのでは?
03:21
ちがうか
03:21
成功のときに
03:21
URLResponseOptional にしたくないのか。
03:22
エラーケースはレスポンス以前に失敗してる可能性があるから Optional だけど
03:22
成功ケースは確実にレスポンスが存在する。
Avatar
omochimetaru 29-Nov-18 03:22 AM
そもそもResponseが取れたけどエラーになるケースってなんなんだろう (edited)
03:22
404だったりしたときでも、Dataに404ページのHTMLが入ってる気がする。
Avatar
koher 29-Nov-18 03:23 AM
うーん、たしかにレスポンスが存在する = Data が存在するな気もするな。
Avatar
omochimetaru 29-Nov-18 03:23 AM
ResponseはとれたけどResponse Bodyを全部受信できずにネットワークが死んだときとか?
Avatar
koher 29-Nov-18 03:23 AM
ヘッダーだけのときとか?
Avatar
omochimetaru 29-Nov-18 03:23 AM
その場合でも、「途中まで取れた分のData」は来るのかな・・・
Avatar
koher 29-Nov-18 03:24 AM
URLSession って 404 はエラーになるんだっけ?
Avatar
omochimetaru 29-Nov-18 03:24 AM
ならなかった気もする。
Avatar
koher 29-Nov-18 03:24 AM
レスポンスが存在する = 成功な気もするなぁ。
Avatar
rintaro 29-Nov-18 03:26 AM
https://developer.apple.com/documentation/foundation/nsurlsession/1407613-datataskwithrequest
If the request completes successfully, the data parameter of the completion handler block contains the resource data, and the error parameter is nil. If the request fails, the data parameter is nil and the error parameter contain information about the failure. If a response from the server is received, regardless of whether the request completes successfully or fails, the response parameter contains that information.
なので、data と error は exclusive だけど、response はエラー時でも入る可能性あることになっていますね。
🙏 1
Avatar
omochimetaru 29-Nov-18 03:27 AM
ありがとうございます。
03:27
前見た時よくわからなかった記憶だったけどちゃんと書いてあった。
Avatar
koher 29-Nov-18 03:28 AM
じゃあやっぱり Proposal の例は URLResponse がエラーケースで失われてるのか・・・
Avatar
omochimetaru 29-Nov-18 03:28 AM
それはちょっと許容できないですね、ブリッジして何か減っちゃまずい。
Avatar
omochimetaru 29-Nov-18 03:40 AM
スレッド追ってみて誰も突っ込んでなければ書き込んでおこう。
03:47
もともとの提案者のJonさんが
03:47
ErrorパラメータにSwift.Errorの制約つけるんであれば、
03:47
valueよりsuccessのほうがいいんじゃない?
03:47
って言ってて面白い。
Avatar
koher 29-Nov-18 04:04 AM
Contribute to koher/SwiftResult development by creating an account on GitHub.
Avatar
omochimetaru 29-Nov-18 04:09 AM
クソリプ失礼した感あるけど書き込んどいた。
04:11
@koher 公式が待てない人用・・・
Avatar
koher 29-Nov-18 04:11 AM
antitypical とかをこれで置き換えておけば移行が簡単。
Avatar
omochimetaru 29-Nov-18 04:12 AM
わかるけどスーパーニッチだ・・・
04:13
@koher case value, errorには賛成なんですか?
04:13
success/failureにしようって意見が結構投稿されてる。
Avatar
koher 29-Nov-18 04:14 AM
特に強い主張はないけど、 value, error でもいいんじゃないかなって感じ。
04:15
↓返事もらえないけど変なこと言ってるかなぁ。 https://forums.swift.org/t/revised-se-0235-add-result-to-the-standard-library/18371/26
I agree on the changes. In particular, it looks great to me that the Error type parameters is constrained to conform to Swift.Error, with self-conformance, and the Result type has minimum APIs. I want a guideline when to use the Result type. Opinions seems divided even in ...
Avatar
omochimetaru 29-Nov-18 04:15 AM
nickさんが11で投稿している
04:15
Success is the status of the Result. The Result was success, and the fruit of that success was a value. The value is not the status, especially (as others have pointed out) since that value may be of type Void in situations where we only care about the status.
04:15
これが、なるほどと思いました。僕は。
04:20
@koher 変では無さそう
Avatar
koher 29-Nov-18 04:21 AM
Result をいつ使うべきかが示されないと throws との使い分けで混乱を生みそう。
04:21
示されても確実にそれが守られなくて混乱を生むだろうけど。 (edited)
Avatar
omochimetaru 29-Nov-18 04:21 AM
proposalで示されている例では非同期と
04:21
すでにthrowsなやつをResult.init(catching:)で捕まえるシナリオだけですね
04:22
最初からResultを返す同期関数の例はないし
Avatar
koher 29-Nov-18 04:22 AM
manual propagation が本当に必要な場合に限定するのか、
Avatar
omochimetaru 29-Nov-18 04:22 AM
JoeGroffも「エラー処理の主なやり方を変えるために導入するのではない」的なことを書いてますね
04:23
Result is a way of storing potential errors; the idea here is not to promote it as a primary way of handling errors.
04:23
しかも例のやつだとそれゆえに全部 <Error>が<Swift.Error>なんですよね
04:23
<Error>を具体的なエラー型で埋めることで網羅検査できる話が出てこない・・・
Avatar
koher 29-Nov-18 04:25 AM
↑の Joe Groff のってどのコメント? (edited)
Avatar
omochimetaru 29-Nov-18 04:25 AM
レス20番。
🙏 1
Avatar
koher 29-Nov-18 04:27 AM
まあ、それだと JSONDecoder.decodethrows のままでいいって考えなのかなぁ?
Avatar
omochimetaru 29-Nov-18 04:27 AM
We know this because some of them have posted in the pitch and review mentioning that they already use their own Result type instead of try-throw-catch. That we can’t actually stop them from doing that is clear from the fact that they’re doing it now
JohnMccallのこのコメントを見てても、
04:27
このスレの1を見てても、
04:27
すでにResult使う人達がいる以上、公式のがあったほうがいいよね、みたいな
04:27
気持ちを感じるというか・・・
Avatar
koher 29-Nov-18 04:28 AM
それを言い出したら、関数型スタイルで書く人がいるからモナドサポートした方がいいよねってなってしまう。
Avatar
omochimetaru 29-Nov-18 04:29 AM
うーんでも実際のところ
04:29
そういうスレッドは
04:29
そんなややこしいのいらなくね、みたいなコメントも付きがち
Avatar
koher 29-Nov-18 04:30 AM
すでにResult使う人達がいる以上
これの 9 割は async/await で解決できる非同期処理だと思うんよね。
Avatar
omochimetaru 29-Nov-18 04:30 AM
Several people expressed hope that a future async/await model would obsolete the most important use-case for Result. The core team agrees that async/await is likely to greatly diminish the importance of this type, but not so much as to make it completely useless, and the type will help standardize existing practice in ways that are likely to be useful for async/await.
Avatar
koher 29-Nov-18 04:30 AM
うん
Avatar
omochimetaru 29-Nov-18 04:30 AM
async/awaitで greatly diminishするって言ってますね。
Avatar
koher 29-Nov-18 04:30 AM
manual propagation が本当に必要な箇所で Result を使うのはいいとして
04:31
Joe Groff のこれ↓は意外だったから、どういう気持なのかを聞きたい。 https://forums.swift.org/t/adding-result-ii-unconstrained-boogaloo/17128/18 (edited)
+1 to an unconstrained, two-argument Result type. Referring back to @John_McCall's original error handling rationale, I think throws and Result can be seen as addressing different corners of the design space. As the rationale describes, throws was designed for systemic errors...
Avatar
omochimetaru 29-Nov-18 04:31 AM
「それでも完全に不要にはならないし、既存のpracticeで使われてるから標準化すると便利だろう」てつないでるからなあ
04:32
あ、でも、既存のpracticeでいえば、RxSwift/RACでの用法は
04:32
Observableはasync/awaitで置換できないから
04:32
そのあたりはガッツリ残るのでは。
Avatar
koher 29-Nov-18 04:32 AM
それはそうだね。
Avatar
omochimetaru 29-Nov-18 04:34 AM
Result on the other hand is great for conditions that are intended to be immediately handled by the caller, for which being an regular return value with a more specific failure type is in fact the more convenient representation.
04:36
この発言をしたときの
04:36
想像してた具体的なシナリオが気になりますね。
04:38
もしかしたら、JSONのdecodeを持ってきたところにすれ違いがあって、よくわからんって思われたのかも?
Avatar
koher 29-Nov-18 05:02 AM
うーん、
I think throws and Result can be seen as addressing different corners of the design space. As the rationale describes, throws was designed for systemic errors, which tend to have a large distance between error source and error handler, so source and handler end up needing to be rather loosely coupled, which was a motivator for the exception-like propagation and lack of specific typing in the current throws feature.
↑は JSON の decode を含まなさそうだけどなぁ。
Avatar
omochimetaru 29-Nov-18 06:02 AM
Note that it's equally unclear how to translate that into async/await, which is not coincidental. async throws -> Data with an inout URLResponse? parameter?
06:02
URLResponseの件、 async/awaitにするときどうすんだべってJohnがw
Avatar
koher 29-Nov-18 06:07 AM
そもそも dataTaskURLSessionDataTaskreturn してるから async/await にできない。
Avatar
omochimetaru 29-Nov-18 06:07 AM
むむ。
Avatar
koher 29-Nov-18 06:08 AM
で、これは API 設計の問題だと思ってて、 URLSessionDataTaskfunc completion() async throws -> (Data, URLResponse) というメソッドを追加するのがいいと思う。
Avatar
omochimetaru 29-Nov-18 06:08 AM
おお〜
Avatar
koher 29-Nov-18 06:08 AM
で、ショートカットでキャンセラーがいらないときは
Avatar
omochimetaru 29-Nov-18 06:09 AM
でもそれだとまだ、エラーのときのURLResponse問題は残ってますね。
Avatar
koher 29-Nov-18 06:09 AM
それは Typed Throws でかいけつする。
Avatar
omochimetaru 29-Nov-18 06:09 AM
struct URLSessionDataTaskError : Error { var response: URLResponse? var error: Error } (Result<(Data, URLResponse), URLSessionDataTaskError>) -> Void
06:09
↑この路線ですか?
Avatar
koher 29-Nov-18 06:09 AM
URLSessionDataTask に func completion() async throws URLSessionDataTaskError -> (Data, URLResponse)
(edited)
Avatar
omochimetaru 29-Nov-18 06:09 AM
いま41として書き込んだんですけど。
06:10
これちょっと変なんですよね
06:10
エラーの実体は内側にあって、そこの型がいろいろかわるので
06:10
responseをアタッチしてるだけのエラー型は
06:10
それ自体エラーを表してるというのは変な気がする。
06:10
Typed throwsも本来はエラーの種類?を表すはずなのに
06:11
「エラーのときの付加情報」を追加するために新しいエラー型が産まれてるのが変な感じが。
Avatar
koher 29-Nov-18 06:11 AM
理想的には
06:11
URLSessionDataTaskenum で色んな case を持ってて
Avatar
omochimetaru 29-Nov-18 06:11 AM
// vvvvvvv ここが気に食わない struct URLSessionDataTaskError : Error {
Avatar
koher 29-Nov-18 06:11 AM
URLResponse を持つ場合だけその caseresponse を保持するのがいいんじゃない?
06:12
enum URLSessionDataTaskError: Error { case ... case ...(URLResponse) ... }
Avatar
omochimetaru 29-Nov-18 06:12 AM
いろんなcaseっていうのは
06:13
URLErrorの中身をそこに昇格するってことですか?
Avatar
koher 29-Nov-18 06:13 AM
URLSessionDataTask がエラーになりうる様々な case
06:13
うん。
06:13
理想的な API にならない理由は Foundation 依存なことだから
06:13
URLSessionDataTaskError 導入してる時点で Foundation との整合性を考える必要性はないのでは。
Avatar
omochimetaru 29-Nov-18 06:14 AM
ふーむ
Avatar
koher 29-Nov-18 06:14 AM
completion の話だけ書き込んでおくか。
Avatar
omochimetaru 29-Nov-18 06:19 AM
もらったレスの英文が全然わからん。
06:23
NSErrorがURLResponseを保持しない事に驚いたって言ってるのかな・・・
Avatar
koher 29-Nov-18 06:25 AM
Because dataTask(with:completionHandler:) returns a URLSessionDataTask, it is impossible to be converted into async/await directly. I think we need an extension method like below. extension URLSessionDataTask { func completion() async throws -> (Data, URLResponse) { ... ...
06:25
completion の件書いておいた
06:28
NSErrorがURLResponseを保持しない事に驚いたって言ってるのかな・・・
概ねそんな感じかと。
Avatar
omochimetaru 29-Nov-18 06:29 AM
なるほど・・・
Avatar
koher 29-Nov-18 06:36 AM
なぜか↓が Linux でだけ失敗する・・・。エラーが起こるけど .dataCorrupted にマッチしてないっぽい。
let jsonData: Data = "".data(using: .utf8)! let result = Result<[Int], Error> { try JSONDecoder().decode([Int].self, from: jsonData) } switch result { case .value(let value): XCTFail("\(value)") case .error(DecodingError.dataCorrupted(let context)): XCTAssertTrue(context.codingPath.isEmpty) case .error(let error): XCTFail("\(error)") }
https://travis-ci.org/koher/SwiftResult/jobs/461127891
06:42
この Result 、 covariance はなくていいんだろうか。特に Result<Int, FooError>Result<Int, Error> に代入できないの辛そう。
Avatar
omochimetaru 29-Nov-18 06:42 AM
b = a.mapError { $0 as Error } ですね。
Avatar
koher 29-Nov-18 06:44 AM
The throwing overload of flatMap should be removed. It is composable from flatMap and init(catching:) , and it is generally frowned upon to overload just on whether something is throwing or not.
06:44
↑と組み合わせると
a.flatMap { Result { try foo() }.mapError { $0 as Error } }
となって辛そう。
06:45
あ、逆か (edited)
06:45
a.flatMap { Result { try foo() }.mapError { $0 as! FooError } }
Avatar
omochimetaru 29-Nov-18 06:55 AM
そうですねえ
06:56
init(catching:)でuntyped throwsを経由することでエラー型が消え去り、でもわかってるから as! でダウンキャスト
06:56
っていうのは微妙なパターンですよね。
Avatar
koher 29-Nov-18 06:57 AM
まあ Result<Foo, Error> を使ってれば問題ないか。
06:58
Error の self-conform で特別扱いするなら、 Result<Value, Error: Swift.Error = Swift.Error> も認めて Result<Foo> って書けるようにしてほしい。
Avatar
omochimetaru 29-Nov-18 07:00 AM
デフォルトジェネリックパラメータ機能が欲しいって意味ですか?
Avatar
koher 29-Nov-18 07:01 AM
とりあえず Result にだけデフォルト型パラを認めてくれたら便利そう。 (edited)
Avatar
omochimetaru 29-Nov-18 07:04 AM
なんかその特別扱いは実装が結構大変そうですね
Avatar
koher 29-Nov-18 07:11 AM
Sema あたりでちょちょいとできないかなぁ。 Result で第二型パラがなかったら Swift.Error と解釈するとか。
Avatar
omochimetaru 29-Nov-18 07:34 AM
import Foundation @objc protocol Animal {} func take<X: Animal>(_ a: X) {} func outer(_ a: Animal) { take(a) }
07:34
proposal読んでて書いてあったんだけど、たしかに、@objcだとself-conformしてる・・・
Avatar
koher 29-Nov-18 08:25 AM
どうやら Swift 4.2 / Linux だと↓のエラーが DecodingError ではなく NSError になるっぽい・・・。
import Foundation do { _ = try JSONDecoder().decode([Int].self, from: "".data(using: .utf8)!) } catch let error { print(error) }
Avatar
omochimetaru 29-Nov-18 08:30 AM
あ、ブリッジが無いからか。
Avatar
koher 29-Nov-18 08:32 AM
Swift 4.2.1 では解決されてる。
Avatar
omochimetaru 29-Nov-18 08:32 AM
そんなタイムリーな。
Avatar
koher 29-Nov-18 08:35 AM
CI がコケるけど手元の Linux 環境で試してもコケないからなんでかと思ったら、 CI の設定が 4.2 で手元は 4.2.1 だった。 4.2.1 に設定しなおしたら CI も通るようになった。
08:35
Linux だけかと思ったけどもしかして macOS でも 4.2 だと NSError なのか。
08:36
@swift-4.0.3 @swift-4.1.3 @swift-4.2.4
import Foundation do { _ = try JSONDecoder().decode([Int].self, from: "".data(using: .utf8)!) } catch let error { print("\(type(of: error)): \(error)") }
(edited)
Avatar
swift42 BOT 29-Nov-18 08:36 AM
DecodingError: ⚠️ [DecodingError.dataCorrupted: The given data was not valid JSON.]
(edited)
Avatar
swift40 BOT 29-Nov-18 08:36 AM
NSError: The operation could not be completed
(edited)
Avatar
swift41 BOT 29-Nov-18 08:36 AM
NSError: The operation could not be completed
(edited)
Avatar
koher 29-Nov-18 08:37 AM
いや、macOS や iOS は 4.2 で も CI 通ってるんだった。 (edited)
Avatar
masakihori 30-Nov-18 02:01 AM
値の取り出しが case let と unwrapped() だけになったのもかなり思い切ってる気がする
02:01
これはこれでいいとは思うが
Avatar
koher 30-Nov-18 02:42 AM
Result のための構文の必要性についても話し合われていたので、将来的に追加されるかもしれませんね。たとえば↓のような構文とかいいかもしれません。
guard let number = result else let error { // error を使うオペレーション } // number を使うオペレーション
Avatar
omochimetaru 30-Nov-18 06:40 AM
Introduce a WinSDK overlay for Windows. This allows us to define some shared constants that are not correctly imported right now. This cleans up the logic in the swift side of things and aids in ...
06:40
@_exported import WinSDK // Clang module // WinBase.h public let HANDLE_FLAG_INHERIT: DWORD = 0x00000001 // WinBase.h public let STARTF_USESTDHANDLES: DWORD = 0x00000100 // WinBase.h public let INFINITE: DWORD = DWORD(bitPattern: -1) // WinBase.h public let WAIT_OBJECT_0: DWORD = 0 // minwindef.h public let FALSE: BOOL = 0 // minwindef.h public let TRUE: BOOL = 1
06:40
WindowsSDKのオーバーレイ!
Avatar
omochimetaru 06-Dec-18 01:28 AM
Hello, Swift Community. The review for the revisions to SE-0235: Add Result to the Standard Library ran from November 28th through December 2nd. You can find the review thread here. There was also an earlier round of review for the initial proposal. The community provided...
01:28
Result型Accepted
👀 3
Avatar
kateinoigakukun 17-Dec-18 02:01 AM
@swift-nightly
protocol P1 { associatedtype Input } protocol P2 { associatedtype Input } struct Box<T> {} extension Box: P1 where T: P1 { typealias Input = T.Input } extension Box: P2 where T: P2 { } func inputType<T>(_ type: T.Type) -> T.Input.Type where T: P2 { fatalError() } struct A: P2, P1 { typealias Input = Int } let _ = inputType(Box<A>.self)
(edited)
Avatar
swiftNightly BOT 17-Dec-18 02:01 AM
exit status: 134 with stderr:
swift: /home/buildnode/jenkins/workspace/oss-swift-package-linux-ubuntu-16_04/llvm/include/llvm/Support/Casting.h:106: static bool llvm::isa_impl_cl<swift::SugarType, const swift::TypeBase *>::doit(const From *) [To = swift::SugarType, From = const swift::TypeBase *]: Assertion `Val && "isa<> used on a null pointer"' failed. Stack dump: 0. Program arguments: /usr/bin/swift -frontend -interpret - -disable-objc-interop -I /Libraries/.build/x86_64-unknown-linux/debug -I /Libraries/.build/checkouts/swift-nio-b68c973e/Sources/CNIOZlib/include -I /Libraries/.build/checkouts/swift-nio-b68c973e/Sources/CNIOHTTPParser/include -I /Libraries/.build/checkouts/swift-nio-b68c973e/Sources/CNIOSHA1/include -I /Libraries/.build/checkouts/swift-nio-b68c973e/Sources/CNIOAtomics/include -I /Libraries/.build/checkouts/swift-nio-b68c973e/Sources/CNIODarwin/include -I /Libraries/.build/checkouts/swift-nio-b68c973e/Sources/CNIOLinux/include -module-cache-path /Libraries/.build/x86_64-unknown-linux/debug/ModuleCache -D DEBUG -Xcc -fmodule-map-file=/Libraries/.build/x86_64-unknown-linux/debug/CNIOZlib.build/module.modulemap -Xcc -fmodule-map-file=/Libraries/.build/x86_64-unknown-linux/debug/CNIOHTTPParser.build/module.modulemap -Xcc -fmodule-map-file=/Libraries/.build/x86_64-unknown-linux/debug/CNIOSHA1.build/module.modulemap -Xcc -fmodule-map-file=/Libraries/.build/x86_64-unknown-linux/debug/CNIOAtomics.build/module.modulemap -Xcc -fmodule-map-file=/Libraries/.build/x86_64-unknown-linux/debug/CNIODarwin.build/module.modulemap -Xcc -fmodule-map-file=/Libraries/.build/x86_64-unknown-linux/debug/CNIOLinux.build/module.modulemap -Xcc -fmodule-map-file=/Libraries/.build/checkouts/swift-nio-zlib-support-c4b8a10c/module.modulemap -module-name main -lLibraries #0 0x000000000460a1c4 PrintStackTraceSignalHandler(void*) (/usr/bin/swift+0x460a1c4) #1 0x0000000004607f90 llvm::sys::RunSignalHandlers() (/usr/bin/swift+0x4607f90) #2 0x000000000460a372 SignalHandler(int)
Avatar
kateinoigakukun 17-Dec-18 02:02 AM
同名associatedtypeがある時のワークアラウンドあったりしますか?
Avatar
Kishikawa Katsumi 17-Dec-18 06:30 AM
@swiftbot --version latest
protocol P1 { associatedtype Input } extension P1 { typealias InputP1 = Input } protocol P2 { associatedtype Input } extension P2 { typealias InputP2 = Input } struct Box<T> {} extension Box: P1 where T: P1 { typealias InputP1 = T.InputP1 } extension Box: P2 where T: P2 { typealias Input = T.InputP2 } func inputType<T>(_ type: T.Type) -> T.Input.Type where T: P2 { fatalError() } struct A: P2, P1 { typealias Input = Int } let _ = inputType(Box<A>.self)
🛠 1
Avatar
swiftbot BOT 17-Dec-18 06:30 AM
Author icon
kishikawakatsumi
protocol P1 { associatedtype Input } extension P1 { typealias InputP1 = Input } protocol P2 { associatedtype Input } extension P2 { typealias InputP2 = Input } struct Box<T> {} extension Box: P1 where T: P1 { typealias InputP1 = T.InputP1 } extension Box: P2 where T: P2 { typealias Input = T.InputP2 } func inputType<T>(_ type: T.Type) -> T.Input.Type where T: P2 { fatalError() } struct A: P2, P1 { typealias Input = Int } let _ = inputType(Box<A>.self)
Version:
swift-DEVELOPMENT-SNAPSHOT-2018-12-15-a
Output:
Error:
Fatal error: file /usercode/main.swift, line 28 Current stack trace: 0 libswiftCore.so 0x00007f51ac83c200 _swift_stdlib_reportFatalErrorInFile + 115 1 libswiftCore.so 0x00007f51ac7773fc <unavailable> + 3396604 2 libswiftCore.so 0x00007f51ac7774ee <unavailable> + 3396846 3 libswiftCore.so 0x00007f51ac582f2a <unavailable> + 1347370 4 libswiftCore.so 0x00007f51ac742f42 <unavailable> + 3182402 5 libswiftCore.so 0x00007f51ac5822f9 <unavailable> + 1344249 8 swift 0x0000000000cec7de <unavailable> + 9357278 9 swift 0x0000000000cf09f2 <unavailable> + 9374194 10 swift 0x0000000000515eff <unavailable> + 1138431 11 swift 0x00000000004eae3e <unavailable> + 962110 12 swift 0x00000000004e6712 <unavailable> + 943890 ...
06:30
Avatar
Kishikawa Katsumi 17-Dec-18 06:30 AM
^ よくわかってないけど、Extensionで別名をつける?
Avatar
kateinoigakukun 17-Dec-18 07:03 AM
@swiftbot --version latest
protocol P1 { associatedtype Input } extension P1 { typealias InputP1 = Input } protocol P2 { associatedtype Input } extension P2 { typealias InputP2 = Input } struct Box<T> {} extension Box: P1 where T: P1 { typealias InputP1 = T.InputP1 } extension Box: P2 where T: P2 { typealias Input = T.InputP2 } func inputTypeP2<T>(_ type: T.Type) -> T.Input.Type where T: P2 { return T.Input.self } func inputTypeP1<T>(_ type: T.Type) -> T.Input.Type where T: P1 { return T.Input.self } struct A: P2, P1 { typealias Input = Int } print(inputTypeP1(Box<A>.self)) // セグフォ print(inputTypeP2(Box<A>.self))
🛠 1
Avatar
swiftbot BOT 17-Dec-18 07:03 AM
Author icon
kateinoigakukun
protocol P1 { associatedtype Input } extension P1 { typealias InputP1 = Input } protocol P2 { associatedtype Input } extension P2 { typealias InputP2 = Input } struct Box<T> {} extension Box: P1 where T: P1 { typealias InputP1 = T.InputP1 } extension Box: P2 where T: P2 { typealias Input = T.InputP2 } func inputTypeP2<T>(_ type: T.Type) -> T.Input.Type where T: P2 { return T.Input.self } func inputTypeP1<T>(_ type: T.Type) -> T.Input.Type where T: P1 { return T.Input.self } struct A: P2, P1 { typealias Input = Int } print(inputTypeP1(Box<A>.self)) // セグフォ print(inputTypeP2(Box<A>.self))
Version:
swift-DEVELOPMENT-SNAPSHOT-2018-12-15-a
Output:
Error:
swift: /home/buildnode/jenkins/workspace/oss-swift-package-linux-ubuntu-16_04/llvm/include/llvm/Support/Casting.h:106: static bool llvm::isa_impl_cl<swift::SugarType, const swift::TypeBase *>::doit(const From *) [To = swift::SugarType, From = const swift::TypeBase *]: Assertion `Val && "isa<> used on a null pointer"' failed. Stack dump: 0. Program arguments: /usr/bin/swift -frontend -interpret /usercode/main.swift -disable-objc-interop -module-name main /usr/bin/swift[0x4608a04] /usr/bin/swift[0x46067d0] /usr/bin/swift[0x4608bb2] /lib/x86_64-linux-gnu/libpthread.so.0(+0x11390)[0x7f533b723390] /lib/x86_64-linux-gnu/libc.so.6(gsignal+0x38)[0x7f5339e62428] /lib/x86_64-linux-gnu/libc.so.6(abort+0x16a)[0x7f5339e6402a] /lib/x86_64-linux-gnu/libc.so.6(+0x2dbd7)[0x7f5339e5abd7] /lib/x86_64-linux-gnu/libc.so.6(+0x2dc82)[0x7f5339e5ac82] /usr/bin/swift[0x19464f3] /usr/bin/swift[0xef6b2c] /usr/bin/swift[0xf0af9e] /usr/bin/swift[0xf0eb07] /usr/bin/swift[0xef3041] /usr/bin/swift[0xe7e311] ...
07:03
Avatar
kateinoigakukun 17-Dec-18 07:03 AM
@Kishikawa Katsumi これだと P1 の方が死んじゃいました
Avatar
omochimetaru 17-Dec-18 07:03 AM
😩
Avatar
Kishikawa Katsumi 17-Dec-18 07:05 AM
難しいな
07:07
しかし、まだこんなくらいのコードでクラッシュさせられるんですね。
Avatar
kateinoigakukun 18-Dec-18 12:30 PM
👍 1
12:30
報告した
Avatar
kateinoigakukun 18-Dec-18 10:54 PM
Typealiases in constrained extensions aren't actually constrained today
22:54
コメントが付いたw
Avatar
omochimetaru 20-Dec-18 01:32 AM
Hello everyone! I'd like to pitch the formalization of ordered collections as well as the addition of diffing functionality and related types necessary to provide easy creation, representation, and application of ordered collection state transitions. Formalizing the notion ...
01:32
標準ライブラリに差分計算入れる話
👀 4
Avatar
norio_nomura 07-Jan-19 06:29 AM
https://github.com/apple/swift/blob/master/include/swift/Runtime/SwiftDtoa.h に入ってるswift_decompose_double(), swift_decompose_float(), swift_decompose_float80()swift_format_exponential()をYamsで使いたかったのだけど、libswiftCoreからexportされていないので、SwiftDtoa.hSwiftDtoa.cppをソースコードごとコピーしてくるしか手が無い。 (edited)
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
06:31
ソースがデカイのと、ライセンスを変えないといけなさそうという理由で、とりあえずクローズ。 https://github.com/jpsim/Yams/pull/151
Use SwiftDtoa.(h|cpp) for formatting FloatingPoint into String Support Float80 as ScalarConstructible and ScalarRepresentable On Linux, Supporting Float80 requires Swift 4.2+, since swift_decompos...
Avatar
omochimetaru 07-Jan-19 06:31 AM
C関数ってヘッダだけ持ってきたらだめなんですっけ
Avatar
norio_nomura 07-Jan-19 06:31 AM
ライブラリでexportされていないとダメです。 (edited)
06:32
nm -gU /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/libswiftCore.dylibで出てくるものならリンクできる。
Avatar
omochimetaru 07-Jan-19 06:33 AM
ふむふむ
06:33
-g Display only global (external) symbols. -U Don't display undefined symbols.
Avatar
norio_nomura 07-Jan-19 06:54 AM
リクエストしておいた。 https://bugs.swift.org/browse/SR-9610
Avatar
omochimetaru 09-Jan-19 12:58 AM
https://github.com/apple/swift-syntax/pull/57 SwiftSyntax公式に、サンプルとして @Kishikawa Katsumi@inamiy の作ったやつへのリンクが追加されそう😀
Avatar
Kishikawa Katsumi 09-Jan-19 01:04 AM
載せてもらいました 💗
Avatar
omochimetaru 10-Jan-19 12:00 PM
SwiftってC言語の可変長引数関数、呼び出せなかったのか
12:02
ブリッジできるのはva_listの場合か・・・
Avatar
norio_nomura 11-Jan-19 03:59 AM
Swift 5のmacOS版のData.withUnsafeBytes(_:)は、Dataが小さい場合にスコープ外で無効となるポインタをクロージャへ渡す場合がある。 https://bugs.swift.org/browse/SR-9578
04:00
「immutableならスコープ外でも使えるポインタだろう」という前提で使っていて、Swift 5になってバグった。
Avatar
omochimetaru 11-Jan-19 04:02 AM
なるほど
04:03
この挙動のときは、Data自体がコンテンツを持っていて、ヒープアロケートを回避してるんですかね
04:03
Small String Optimizationみたいな感じで。
04:04
あ、じゃあ String の withCString { } とかも同じ事がありえるのかな
04:04
逆にどんなときテンポラリなポインタが来るのか気になってたけどこういうケースがあるんだなあ
Avatar
norio_nomura 11-Jan-19 04:14 AM
withCString(_:)は、null termination追加があるから以前から毎回一時メモリじゃないかな。 (edited)
Avatar
omochimetaru 11-Jan-19 04:15 AM
文字列ライブラリってとりあえずCに備えて いつもnullつけてバッファ保持したりもするのでそれを期待してました
Avatar
rintaro 11-Jan-19 04:16 AM
Swift5 の通常の String のストレージは UTF8 で null terminated になるで、 5 からは大抵ストレージへの直ポインタになりそう。
Avatar
norio_nomura 11-Jan-19 04:18 AM
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
Avatar
rintaro 11-Jan-19 04:19 AM
String’s ABI and UTF-8 We just landed String’s proposed final ABI on master. This ABI includes some significant changes, the primary one being that native Swift strings are stored as UTF-8 where they were previously stored either as ASCII or UTF-16 depending on their cont...
Avatar
norio_nomura 11-Jan-19 04:22 AM
Small UTF-8 Stringsも言及されてますね。
Avatar
norio_nomura 11-Jan-19 04:41 AM
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
04:41
swift-corelibs-foundationには無い。
03:03
Adds an on_stack version of partial_apply It does not take ownership of its non-trivial arguments, is a trivial function type and therefore must not be destroyed. The compiler must make sure to ext...
Avatar
omochimetaru 17-Jan-19 03:05 AM
おー
03:05
クロージャの環境オブジェクトがスタックに作れるようになったのかな?
Avatar
norio_nomura 17-Jan-19 03:06 AM
Avatar
omochimetaru 17-Jan-19 03:06 AM
17倍のやつやばいですね
Avatar
norio_nomura 17-Jan-19 03:09 AM
non-escaping functionsの変遷を簡単に解説してる。 https://twitter.com/slava_pestov/status/1085691914328920066 (ツイート内のリンクは上記PR) (edited)
Short history of non-escaping functions: - Swift 4.1 and earlier: type checker enforcement; same ABI as escaping - Swift 4.2: new ABI - the context is a trivial pointer and not ref-counted like with escaping - now: non-escaping contexts allocated on stack https://t.co/gIl...
Avatar
omochimetaru 17-Jan-19 03:10 AM
non-escapingの時にtrivial pointerになったのって4.2だったのか。ちょうど最近見た。
Avatar
kateinoigakukun 18-Jan-19 03:46 AM
protocol Animal {} protocol Cat: Animal {} protocol Owner { associatedtype Pet var pet: Pet { get } } func callBark(_ animal: Animal){} func callPetBark<T: Owner>(_ t: T) where T.Pet == Animal { callBark(t.pet) } func callPetBark<T: Owner>(_ t: T) where T.Pet == Cat { callBark(t.pet) } struct Lion: Cat {} struct Breeder: Owner { typealias Pet = Animal var pet: Animal { return Lion() } } let owner = Breeder() callPetBark(owner)
assoctypeが「あるexistentialのサブタイプである」、っていう制約を書きたい
(edited)
03:47
要はcallPetBarkのオーバーロードを無くしたいんですけど、なんかいい方法無いですか? (edited)
Avatar
norio_nomura 18-Jan-19 04:01 AM
BreederpetAnimalである時点で無理そう。 error: protocol type 'Animal' cannot conform to 'Animal' because only concrete types can conform to protocols にハマる。
Avatar
omochimetaru 18-Jan-19 04:08 AM
protocol Animal {} protocol Cat: Animal {} protocol Owner { associatedtype Pet var pet: Pet { get } } func callBark(_ animal: Animal){} func callPetBark<T: Owner>(_ t: T) where T.Pet : Animal { callBark(t.pet) } struct Lion: Cat {} struct GenericBreeder<T>: Owner { typealias Pet = T init(pet: T) { self.pet = pet } var pet: T } struct AnyAnimal : Animal { var value: Animal } struct AnyAnimalBreeder : Owner { init<X: Animal>(pet: X) { self.pet = AnyAnimal(value: pet) } var pet: AnyAnimal } struct ConcreteLionBreeder : Owner { typealias Pet = Lion var pet: Lion { return Lion() } } let o1 = GenericBreeder<Lion>(pet: Lion()) callPetBark(o1) let o2 = AnyAnimalBreeder(pet: Lion()) callPetBark(o2) let o3 = ConcreteLionBreeder() callPetBark(o3)
04:08
直接の解答は思いつかなかった。代替を3種↑
Avatar
norio_nomura 18-Jan-19 04:09 AM
やはりそうなるよね。
Avatar
kateinoigakukun 18-Jan-19 04:09 AM
うーんやっぱりそうですねーー
Avatar
omochimetaru 18-Jan-19 04:09 AM
ex.Animal と ex.Cat の間にはサブタイピング関係があるけど、 素直に where T.Pet : Animal と書いてしまうと、exisとは関係ないプロトコル制約の意味になっちゃって、 それが使えないねえ
Avatar
kateinoigakukun 18-Jan-19 04:10 AM
そうなんですよ、 where句でexistentialとprotocolが区別できればいいんですけど。
Avatar
omochimetaru 18-Jan-19 04:14 AM
うーんどこに歪みがあるのかもよくわからんなこの話
04:15
Animalを避けてAnyAnimalを手実装するのがマシな路線な気がする
Avatar
kateinoigakukun 18-Jan-19 04:22 AM
既存コードの後方互換を保つのが目的なのでBreederにできるだけ変更入れたく無いんですよね。。
04:23
大人しくオーバーロード書くことにします 😿
Avatar
nekonoki 18-Jan-19 06:43 AM
@swift-4.2.4
import Foundation enum Key: String, Decodable { case a, b, c } let json = """ { "a": "__a__", "b": "__b__", "c": "__c__" } """.data(using: .utf8)! do { print(try JSONDecoder().decode([String: String].self, from: json)) let ret = try JSONDecoder().decode([Key: String].self, from: json) print(ret) } catch { print(error) }
(edited)
Avatar
swift42 BOT 18-Jan-19 06:43 AM
["a": "__a__", "c": "__c__", "b": "__b__"] ⚠️ [DecodingError.typeMismatch: Value of type 'Array<Any>' required for key ''.]
(edited)
Avatar
nekonoki 18-Jan-19 06:48 AM
今更ですが、Decodable の Dictionary のキーは String か Int しか受け付けてなかったんですね 😇 (入力が配列であれば任意のキーで Dictionary にはできるっぽいですが。。) https://github.com/apple/swift/blob/master/stdlib/public/core/Codable.swift.gyb#L1893
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
Avatar
omochimetaru 18-Jan-19 07:03 AM
extension Dictionary : Decodable where Key : Decodable, Value : Decodable {
↑このとおり、KeyがDecodableなら、StringやIntではない型も使えると思います
07:03
ただ、StringとIntじゃないと、KeyedContainerにならないので
07:04
それ以外のものでDecodableの場合は、UnkeyedContainerからkeyとvalueを交互に取り出すっていう
07:04
挙動になりますね
07:04
JSONのobjectからデコードするという意味だとStrintとIntしか駄目ですが、 JSONのarrayからなら変なKeyもいける。
👏 1
Avatar
nekonoki 18-Jan-19 07:26 AM
今まで [Int: User] だったものを [UserId: User] のような感じにしたかったんですが、直接やるのは少し難しいですね 😢 (edited)
Avatar
omochimetaru 18-Jan-19 07:27 AM
それだと一度 [Int: User]でdecodeしてからmapするのが良さそうですね
Avatar
tarunon 18-Jan-19 07:28 AM
keyのmapって面倒くさくなかったでしたっけ
07:28
mapValuesはあるけどmapKeysは無いような 🤔
Avatar
omochimetaru 18-Jan-19 07:29 AM
let a: [Int: String] = [1: "a", 2: "b"] let b: [String: String] = Dictionary(uniqueKeysWithValues: a.map { ("\($0)", $1) })
07:30
// むりやり左から右の流れに・・・ let c: [String: String] = Optional(a.map { ("\($0)", $1) }).map(Dictionary.init)!
Avatar
norio_nomura 18-Jan-19 07:36 AM
Dictionaryの代わりを作るとか…
Avatar
nekonoki 18-Jan-19 07:55 AM
ありがとうございます。ひとまず map で凌ごうと思います。 (確かに独自 Dictionary はインターフェース的にきれいに表現できそうです 😄
Avatar
tarunon 18-Jan-19 11:46 AM
これはちょっと僭越なんですが、Responseの段階では単なる[User]になってた方が取り回しが良さそう… (edited)
Avatar
norio_nomura 01-Feb-19 12:02 AM
https://discordapp.com/channels/291054398077927425/291054454793306112/539692829606281243 encodedOffsetdeprecatedにする提案をswift-5.0-RELEASEへ入れるには遅すぎた、という結論へ至ったらしい。まあ仕方ない。 https://forums.swift.org/t/se-0241-explicit-encoded-offsets-for-string-indices/19929/36 (edited)
The original proposal sought to solve 3 problems: SE-0180’s encodedOffset, meant for serialization purposes, needs to be parameterized over the encoding in which the string will be serialized in Existing uses of encodedOffset need a semantics-preserving off-ramp for Swift...
😍 1
Avatar
norio_nomura 01-Feb-19 12:12 AM
あいや、swift-5.0-RELEASEへ入れるのを諦めるのは各offsetに対応したAPIを追加する事で、encodedOffsetdeprecatedにして代替となるString.Index.utf16Offset(in:)String.Index.init(utf16Offset:in:)だけはswift-5.0-RELEASEへ入れようという方向へ切り替わったのか? https://github.com/apple/swift-evolution/blob/master/proposals/0241-string-index-explicit-encoding-offset.md (edited)
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
Avatar
omochimetaru 01-Feb-19 01:50 AM
Detailed Designが全然違うものになってるw
Avatar
omochimetaru 01-Feb-19 02:02 AM
ジェレミーさんの指摘の 「That is trivially composable.」は全くそのとおりだなあ
Avatar
omochimetaru 01-Feb-19 07:46 AM
エンコード違いの文字列同士の間のIndexが半順序(partially order)になるというの面白いですね
07:46
なかなかpartially orderって現実で直面する事が無いけどこの例は身近だし。
Avatar
omochimetaru 01-Feb-19 08:12 AM
やっと読めた。
08:12
The original proposal sought to solve 3 problems: SE-0180’s encodedOffset, meant for serialization purposes, needs to be parameterized over the encoding in which the string will be serialized in Existing uses of encodedOffset need a semantics-preserving off-ramp for Swift...
08:14
コアチーム的に新しい事をSwift5.0に追加するにはおそすぎるけど、 内部がUTF-8になる事によって、元々のUTF-16のつもりでやってたやつを移行する(semantics-preserving)APIだけは緊急に必要で(urgent fixes)
08:16
という話か。一つ前の>>35でも興味深い指摘がされてますね。
08:17
元々正しい書き換えして出ていた、 string.utf16.index(string.startIndex, by: offset) という書き方だと (edited)
08:17
もともとは String.Index(encodedOffset: offset) でパラメータがoffsetだけだったのに対して
08:17
対象のstringが必要になっちゃってる
08:18
で、NSString系のNSRangeが返ってくる系のコールバックだと
08:18
func processEdit(editedNSRange: NSRange, changeInLenght delta: Int) { let editedRange = Range<String.Index>(uncheckedBounds: ( String.Index(encodedOffset: editedNSRange.lowerBound), String.Index(encodedOffset: editedNSRange.upperBound) )) ...
08:18
こういうふうに元々stringなしでNSRangeからRange<String.Index>に持っていけてたから
08:19
この用途をカバーするAPIが必要なんですね。
08:20
あれ?修正提案でも
public init<S: StringProtocol>(utf16Offset offset: Int, in s: S) {
こうなってるな。
Avatar
norio_nomura 01-Feb-19 10:39 AM
String.Indexはオフセットが同じでも、対象となるStringにより中身が変わってきます。 コメントに構造が記されてます。 https://github.com/apple/swift/blob/master/stdlib/public/core/StringIndex.swift#L17-L33
/* String's Index has the following layout: ┌──────────┬───────────────────┬────────────────┬──────────┐ │ b63:b16 │ b15:b14 │ b13:b8 │ b7:b0 │ ├──────────┼───────────────────┼────────────────┼──────────┤ │ position │ transcoded offset │ grapheme cache │ reserved │ └──────────┴───────────────────┴────────────────┴──────────┘ - grapheme cache: A 6-bit value remembering the distance to the next grapheme boundary - position aka `encodedOffset`: An offset into the string's code units - transcoded offset: a sub-scalar offset, derived from transcoding The use and interpretation of both `reserved` and `grapheme cache` is not part of Index's ABI; it should be hidden behind non-inlinable calls. However, the position of the sequence of 14 bits allocated is part of Index's ABI, as well as the default value being `0`. */
(edited)
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
Avatar
omochimetaru 01-Mar-19 12:35 AM
Hey all, I'm very excited to bring this pitch today to get more feedback from the community—it's an effort that my team at Google has been doing in collaboration with @dabrahams (co-author) and many other folks on the Swift team. SE pull request. An Official Style Guide ...
00:37
グーグルがしこしこ作ってたフォーマッターのピッチが書き込まれた
00:37
6時間で70レスついてる
Avatar
norio_nomura 01-Mar-19 12:50 AM
Should the Swift language adopt an official style guide and formatting tool?
これに割かれるリソースを想像すると、賛成しづらいね。
(edited)
Avatar
omochimetaru 01-Mar-19 01:00 AM
現状だとxcodeの微妙なフォーマットが半分オフィシャルみたいなもので、 それとswiftlintが併用されてたりするから、
01:01
言語オフィシャルが決まればxcodeも追従するとしたら、それが嬉しいな
01:02
go fmtやpython pep8はどうやって決着したんだろ
Avatar
norio_nomura 01-Mar-19 01:30 AM
Official Style Guideが決まったとしても、apple/swift自体がそれを使ってなければ説得力に欠けるよね。
Avatar
Kishikawa Katsumi 01-Mar-19 01:44 AM
極端に変じゃなくて自動的に適用される環境が簡単に手に入るようになれば使われるはず。
Avatar
omochimetaru 01-Mar-19 01:48 AM
公式として提供するのはフォーマットシステムにしてプロジェクト単位でカスタムできる機構があるといい、みたいな意見がちらほら書かれてるなあ
Avatar
norio_nomura 01-Mar-19 04:29 AM
まあ、標準でToolchainに入ってれば使うのかな?というか今入ってるのは、使われてるのかな? @swift-4.2.4 format --help
Avatar
swift42 BOT 01-Mar-19 04:29 AM
exit status: 1 with stdout:
OVERVIEW: Swift Format Tool USAGE: swift [options] <inputs> OPTIONS: -help Display available options -in-place Overwrite input file with formatted file. -indent-switch-case Indent cases in switch statements. -indent-width <n> Number of characters to indent. -line-range <n:n> <start line>:<end line>. Formats a range of lines (1-based). Can only be used with one input file. -o <file> Write output to <file> -tab-width <n> Width of tab character. -use-tabs Use tabs for indentation.
Avatar
omochimetaru 01-Mar-19 04:31 AM
rzyzanowskim Marcin Krzyzanowski 7h I just want to mention this probably the most forgotten tool that is part of the toolchain for a long time already.
04:31
それに誰も触れないからスレの終盤で指摘があった
04:31
akyrtzi Argyrios Kyrtzidis This is wrapping the C++ code that is doing indentation only and is not a good base to build a proper formatter on; it would be much better to use a formatter tool written in Swift.
04:32
akyrtziさんはSyntaxチームの人
06:10
Google CodeLabでpython notebook風にSwift For TensorFlow動いとる
Avatar
norio_nomura 10-Mar-19 04:53 AM
Linuxは#available(macOS 10.13, *)trueになる。 @swift-5.0.3
if #available(macOS 10.13, *) { print("#available(macOS 10.13, *)") } else { print("not #available(macOS 10.13, *)") }
Avatar
swift50 BOT 10-Mar-19 04:53 AM
#available(macOS 10.13, *)
Avatar
norio_nomura 10-Mar-19 05:10 AM
この挙動はあてにしても良いのだろうか?
Avatar
koher 11-Mar-19 04:00 PM
おや・・・
protocol Foo {} extension Int: Foo {} protocol P { associatedtype F: Foo func foo1() -> F func foo2() -> F } struct S { func foo1() -> __opaque Foo { return 2 } func foo2() -> __opaque Foo { return 3 } } let s = S() var a = s.foo1() let b = s.foo2() a = b
/path/to/opaque-result.swift:17:5: error: cannot assign value of type '(__opaque main.(file).S.foo2()@/path/to/opaque-result.swift:11:10)' to type '(__opaque main.(file).S.foo1()@/path/to/opaque-result.swift:10:10)' a = b ^ as! (__opaque main.(file).S.foo1()@/path/to/opaque-result.swift:10:10)
(edited)
16:03
↓こちらをビルドして試した結果。 https://github.com/jckarter/swift/tree/opaque-type-ast
The Swift Programming Language. Contribute to jckarter/swift development by creating an account on GitHub.
16:03
↓こっちの方がいいのかな? Proposal からリンクされてた PR のブランチは↑だけど。 https://github.com/jckarter/swift/tree/opaque-type-runtime (edited)
The Swift Programming Language. Contribute to jckarter/swift development by creating an account on GitHub.
16:08
↓こっちはそもそも -> (some Foo, some Foo) が現時点で許されてなかった。
protocol Foo {} extension Int: Foo {} protocol P { associatedtype F: Foo func foos() -> (F, F) } struct S { func foos() -> (__opaque Foo, __opaque Foo) { return (2, 3) } } let s = S() var (a, b) = s.foos() a = b
/path/to/opaque-result-2.swift:9:21: error: 'opaque' types are only implemented for the declared type of properties and subscripts and the return type of functions func foos() -> (__opaque Foo, __opaque Foo) { return (2, 3) } ^
(edited)
Avatar
koher 11-Mar-19 04:19 PM
SS: P にできてなかった・・・
16:19
protocol Foo {} extension Int: Foo {} protocol P { associatedtype F: Foo func foo1() -> F func foo2() -> F } struct S: P { func foo1() -> __opaque Foo { return 2 } func foo2() -> __opaque Foo { return 3 } } let s = S() var a = s.foo1() let b = s.foo2() a = b
/path/to/opaque-result.swift:9:8: error: type 'S' does not conform to protocol 'P' struct S: P { ^ /path/to/opaque-result.swift:5:20: note: ambiguous inference of associated type 'F': '(__opaque main.(file).S.foo2()@/path/to/opaque-result.swift:11:10)' vs. '(__opaque main.(file).S.foo1()@/path/to/opaque-result.swift:10:10)' associatedtype F: Foo ^ /path/to/opaque-result.swift:11:10: note: matching requirement 'foo2()' to this declaration inferred associated type to '(__opaque main.(file).S.foo2()@/path/to/opaque-result.swift:11:10)' func foo2() -> __opaque Foo { return 3 } ^ /path/to/opaque-result.swift:10:10: note: matching requirement 'foo1()' to this declaration inferred associated type to '(__opaque main.(file).S.foo1()@/path/to/opaque-result.swift:10:10)' func foo1() -> __opaque Foo { return 2 } ^ /path/to/opaque-result.swift:17:5: error: cannot assign value of type '(__opaque main.(file).S.foo2()@/path/to/opaque-result.swift:11:10)' to type '(__opaque main.(file).S.foo1()@/path/to/opaque-result.swift:10:10)' a = b ^ as! (__opaque main.(file).S.foo1()@/path/to/opaque-result.swift:10:10)
16:22
Sfoo1foo2__opaque Foo が別の型とみなされてるっぽい。
16:22
↓は OK
protocol Foo {} extension Int: Foo {} protocol P { associatedtype F: Foo func foo() -> F } struct S: P { func foo() -> __opaque Foo { return 42 } } let s = S() var a = s.foo() let b = s.foo() a = b
Avatar
tarunon 11-Mar-19 04:22 PM
一個までならいけるんですかね
16:22
おおーーー
Avatar
koher 11-Mar-19 04:32 PM
↓これなら複数 API の戻り値型間で代入できました。
protocol Foo {} extension Int: Foo {} protocol P { associatedtype F: Foo func makeFoo(from: Int) -> F func foo() -> F } struct S: P { func makeFoo(from: Int) -> __opaque Foo { return from } func foo() -> F { return makeFoo(from: 42) } } let s = S() var a = s.foo() let b = s.makeFoo(from: -1) print(a) a = b print(a)
42 -1
Avatar
tarunon 11-Mar-19 04:32 PM
Avatar
koher 11-Mar-19 04:32 PM
なぜか同じ要領で foo1foo2 を作るとエラーになる・・・
Avatar
tarunon 11-Mar-19 04:32 PM
フーム
Avatar
koher 11-Mar-19 04:33 PM
仕様なのか、作りかけなのか判断できませんね・・・
16:34
このブランチが opaque-type-ast で、最近 Joe Groff が触ってるっぽい opaque-type-runtime が別にありますし。
Avatar
tarunon 11-Mar-19 04:36 PM
宣言箇所が一箇所ならok?
Avatar
koher 11-Mar-19 04:36 PM
お、↓も通った。
protocol Foo {} extension Int: Foo {} protocol P { associatedtype F: Foo func foo() -> F func foos() -> (F, F) } extension P { func foos() -> (F, F) { return (foo(), foo()) } } struct S: P { func foo() -> Int { return Int.random(in: 0..<100) } } let s = S() var (a, b) = s.foos() print(a) a = b print(a)
9 52
Avatar
tarunon 11-Mar-19 04:36 PM
typealias F = some Foo にして返り値はF
Avatar
koher 11-Mar-19 04:38 PM
typealias で opaque result type はまだ許されてないようです。
protocol Foo {} extension Int: Foo {} protocol P { associatedtype F: Foo func foo() -> F } struct S: P { typealias F = __opaque Foo func foo() -> F { return 42 } } let s = S() var a = s.foo() let b = s.foo() a = b
/path/to/opaque-result-0.swift:9:19: error: 'opaque' types are only implemented for the declared type of properties and subscripts and the return type of functions typealias F = __opaque Foo ^
Avatar
tarunon 11-Mar-19 04:39 PM
うーんわからん
Avatar
koher 11-Mar-19 04:40 PM
associatedtype を確定する typealias とは別ですが、一般的な typealias は今回の Proposal 外の Future Directions に入ってるので、 protocol でも将来的なサポートになるかもです。 https://github.com/apple/swift-evolution/blob/master/proposals/0244-opaque-result-types.md#opaque-type-aliases (edited)
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
16:43
とりあえず、↑の実験から、 associatedtype の型を具象型側で some Foo にした場合、 some Foo を返す複数 API 間で同一の型として扱えそうです。
16:50
=== 明示的に記述しなければ (some Foo)? 作れた🤔
protocol Foo {} extension Int: Foo {} protocol P { associatedtype F: Foo func foo() -> F func fooOrNil() -> F? } struct S: P { func foo() -> __opaque Foo { return 42 } func fooOrNil() -> F? { return Bool.random() ? foo() : nil } } let s = S() var a = s.fooOrNil() print(String(describing: a)) let b: Int? = -1 a = b // Error
/path/to/opaque-result-3.swift:19:5: error: cannot assign value of type 'Int?' to type '(__opaque main.(file).S.foo()@/path/to/opaque-result-3.swift:10:10)?' a = b // Error ^ as! (__opaque main.(file).S.foo()@/path/to/opaque-result-3.swift:10:10)
(edited)
Avatar
tarunon 11-Mar-19 04:50 PM
これはw
Avatar
koher 11-Mar-19 04:51 PM
エラーの行コメントアウトしたらコンパイルも通って実行もできます。
Avatar
omochimetaru 12-Mar-19 01:50 AM
Another way we could conceivably notate this is by putting the output parameters after the ->, as a number of people suggested:
makeFoo() -> <F: Foo> F
↑この記法は何が起きてるかわかりやすいと思った
(edited)
01:50
In Swift, this would mean that:
func foo(x: some P) { /* ... */ }
would be sugar for:
func foo<T: P>(x: T) { /* ... */ }
(edited)
01:52
some P ってのは結局、暗黙のジェネリックパラメータで、引数部分で使う場合は通常のジェネリクスと同じ事 返り値で使う場合だと、パラメータをcallerではなくcalleeが決定するという違いが出る
01:52
その点で、 makeFoo() -> <F: Foo> F ←これは見た目的に直感的にそれが伝わる
Avatar
koher 12-Mar-19 01:56 AM
使う側は明示的に指定できない?
Avatar
omochimetaru 12-Mar-19 01:57 AM
opaque result typeはその名の通り本当の型は関数側で静的に決まってて、受け取り側(caller)がジェネリックコンテナで受け取るというだけなので
01:58
使う側からの明示的な指定は無理、だと思います
Avatar
koher 12-Mar-19 01:58 AM
あと、戻り値以外のケースでも問題ないかな?
let a: <F: Foo> F = makeFoo() typealias Bar = <F: Foo> F
Avatar
omochimetaru 12-Mar-19 01:59 AM
こういうのはいけるか、今回の提案だと範囲外?だけど
func makeColl<X>() -> some Collection<.Element == X>
(edited)
Avatar
koher 12-Mar-19 01:59 AM
同じ見た目の型間で代入できない問題があって、それなら使う側が名前をつけて区別できてもいいと思うけどなぁ。
02:00
some Foosome Foo なら英語的に別の型を意味しそうという利点はある。
Avatar
omochimetaru 12-Mar-19 02:00 AM
使う側が名前をつけてってどういう意味ですか?
02:00
名前がほしいならそもそもの(Motivationの) struct LazyMapCollection で書けば良い気がしますが (edited)
Avatar
koher 12-Mar-19 02:01 AM
foo1 の返す some Foo には Bar と名前をつけて、 foo2 の返す some Foo には Baz と名前をつければ↓のようなことは起こらない。
var a: some Foo = foo1() let b: some Foo = foo2() a = b // `some Foo` と `some Foo` は字面上同じ型っぽいけど別の型なのでエラー
02:02
名前がほしいならそもそもの(Motivationの) struct LazyMapCollection で書けば良い気がしますが
実装上の型を露出しない上での話。
Avatar
omochimetaru 12-Mar-19 02:03 AM
でも Foo は実際にはプロトコル名だから、some Fooを変えようがないような (edited)
Avatar
koher 12-Mar-19 02:04 AM
↓みたいな何かでもいいのかもしれないけど、 -> <F: Foo> F のような記法を導入するなら何かジェネリクス的な記法で解決できないかなと。特に具体的なアイデアがあるわけじゃないけど。
typealias Bar = foo1.(some Foo) typealias Baz = foo2.(some Foo)
Avatar
omochimetaru 12-Mar-19 02:05 AM
↑opaque typealiasをつけたところで、 依然として some Fooで受ける形にかけちゃいますよね
Avatar
koher 12-Mar-19 02:06 AM
↓みたいにすると、 foo1some Foo 間で別名を付けれてしまうので微妙。
var a: Bar = foo1()<Bar> let b: Baz = foo2()<Baz> a = b // エラー: `Bar` を `Baz` に代入できないのは自然に見える let c: Qux = foo1()<Qux> a = c // `foo1` の `some Foo` に別の名前を与えられてしまっている
02:06
↑opaque typealiasをつけたところで、 依然として some Fooで受ける形にかけちゃいますよね
なので、 some Foo ではなく -> <F: Foo> F を採用したとして、うまく馴染む記法はないかなぁと。
02:08
=== ↓これ、 where 後置記法を導入しちゃったから where でやろうとすると混ざっちゃうよね。 <> の中に書けばいけるかもだけど、引数側の型パラと並ぶとややこしそう。
こういうのはいけるか、今回の提案だと範囲外?だけど
func makeColl<X>() -> some Collection<.Element == X>
(edited)
02:10
↓みたいになりそう。
func makeColl<X: Foo>() -> <C: Collection where C.Element == X> C where X.Bar == Int
(edited)
02:10
しかも、戻り値側の where だけ後置できないの微妙。
02:10
あまり where の後置好きじゃない。
Avatar
omochimetaru 12-Mar-19 02:11 AM
そもそも、: some Foo をつけずに
var a = foo1() let b = foo2() a = b // エラー
02:11
これだったら、普通のことだから、
02:11
そこの特殊性が some という新しいキーワードによって表現されていて (edited)
02:12
これまでにRustぐらいでしかない概念だからなじまないだけで、プログラマの常識がアップデート前だから変に感じちゃうだけな気もする。
02:13
エラーメッセージでは関数名まで含んだ匿名な型名が出てくるしそこで理解できる気も。
as! (__opaque main.(file).S.foo()
02:14
func makeColl<X: Foo>() -> <C: Collection where C.Element == X> C where X.Bar == Int
↑これを推してる人もいるっぽいですね。明示的なCが手に入るのが良いところ
Avatar
kateinoigakukun 12-Mar-19 02:14 AM
全てのsome Fooが代入不可ならシュッと受け入れられるんですけど、代入できるやつとできないやつが同じ型で表現されるのが… と思ったけどエラーメッセージに関数プレフィックス付くんですね
Avatar
koher 12-Mar-19 02:17 AM
全てのsome Fooが代入不可ならシュッと受け入れられるんですけど、代入できるやつとできないやつが同じ型で表現されるのが…
うん、これが引っかかってて、可読性が落ちそう・・・。エラーメッセージで出ても、レビューしてるときとか、すぐに同じ型かどうか判断できなさそう。
Avatar
omochimetaru 12-Mar-19 02:18 AM
明示的なCがあると、
func makeColls() -> <C: Collection, D: Collection> (C, D) where D.Element ==C { return ([1,2,3] , [ [1], [2] ]) }
こういうのが書けますね
02:18
たしかに「代入できる場合である」ことの可読性は低いですねえ。
Avatar
koher 12-Mar-19 02:18 AM
ただ、とりあえず現状( opaque-type-ast ブランチ)では変数の型として some Foo を書くことはできないみたいです。仕様なのか現状の実装状況がそうなだけなのかわからないけど。
Avatar
omochimetaru 12-Mar-19 02:19 AM
public protocol P { mutating func flip() } private struct Witness: P { mutating func flip() { /* ... */ } } public var someP: some P = Witness()
02:19
プロポーザルとしては↑をふくんでいますよ
Avatar
koher 12-Mar-19 02:20 AM
public がついてるのはグローバル変数だから、ローカル変数とは扱いが異なるかも。
Avatar
kateinoigakukun 12-Mar-19 02:21 AM
internalな変数なら実装都合の型が露見しても良いってことですかね (edited)
Avatar
omochimetaru 12-Mar-19 02:22 AM
let strings: some Collection = ["hello", "world"]
02:22
その上に↑これがあった
Avatar
koher 12-Mar-19 02:22 AM
internalな変数なら実装都合の型が露見しても良いってことですかね
たしかにそれなら露見しても良さそうだけど、型推論なら some Foo で受けられるわけだし、変数で禁止する必要もなさそうに思います。
(edited)
Avatar
omochimetaru 12-Mar-19 02:22 AM
For computed properties, the concrete type is determined by the return statements in the getter. Opaque result types can also be used in stored properties that have an initializer, in which case the concrete type is the type of the initializer:
Avatar
koher 12-Mar-19 02:23 AM
どこかに variables とも書いてあった気がするんだけど、
02:23
現状では、プロパティはいいけど変数はダメだぜ的なエラーメッセージが出る。
Avatar
omochimetaru 12-Mar-19 02:25 AM
internalな変数なら実装都合の型が露見しても良い
そもそも右辺値に来るfuncのシグネチャ定義の時点でopaque typeだから、実装の型はわからんのでは
(edited)
Avatar
kateinoigakukun 12-Mar-19 02:28 AM
単純に例として挙げてるのかと思ったら明確にエラーになるんですね、そうすると分からなくなってきた
Avatar
omochimetaru 12-Mar-19 02:28 AM
型推論に対する明示的な記法みたいに、 opaque typeに対する明示的な記法として、caller側で、
var a: some Foo (S.foo1) = s.foo1() let b: some Foo (S.foo2) = s.foo2() a = b // 納得できる代入エラー
(edited)
02:28
みたいに書けたらどうでしょう?
02:30
protocolによるassociated typeでfoo1とfoo2が同じsome Fooとして拘束されている場合は
var a: some Foo (P.FooType) = s.foo1() let b: some Foo (P.FooType) = s.foo2() a = b
と書かないとだめ。
(edited)
02:31
opaque type の真の型が難しいのは、func固有の型だったり、型固有の型(inner typeのような)だったりする場合があることですよね。
02:32
とすると、caller側でそのコンテキストを明記しておいてそれをコンパイラが検証すれば
02:32
わかってあってればあってることが確認できる。
Avatar
koher 12-Mar-19 02:33 AM
引数 some Foo はシンタックスシュガーになるみたいなので、戻り値 some Foo も後からシュガーにできるのかな?
func makeFoo() -> some Foo { /*...*/ } // ↑を↓のシュガーにできる? func makeFoo() -> <F: Foo> F { /*...*/ }
Avatar
omochimetaru 12-Mar-19 02:33 AM
上から下はいけるけど、下から上は駄目な場合がありそう。
02:34
下だと書けるパターンが出てくる気がする。
Avatar
koher 12-Mar-19 02:34 AM
func useFoo(_ foo: some Foo) { /* ... */ } // ↑は↓のシュガーとして将来的に導入される模様 func useFoo<F: Foo>(_ foo: F) { /* ... */ }
Avatar
omochimetaru 12-Mar-19 02:34 AM
func makeFooPair() -> <F: Foo> (F, F) { /*...*/ }
Avatar
koher 12-Mar-19 02:34 AM
上から下だけでいいんじゃない?
Avatar
omochimetaru 12-Mar-19 02:35 AM
コメントの↑と↓が(相互に)って意味かと思った。
02:35
上から下だけはいけると思う。
Avatar
koher 12-Mar-19 02:35 AM
ただ、上が先に導入されることで、下の表現力がなくなってしまって、 -> <F: Foo> (F, F) みたいなのを ABI 上位表現できなくなったりしないかなと。
Avatar
omochimetaru 12-Mar-19 02:35 AM
それは追加的だからどうにかなりそうです
02:36
上の表現に収まる場合は上のABIでコード生成して
02:36
はみ出る場合は新しいABIで生成すれば、古いバイナリが新しい機能をリンクしようとすることがないので。
Avatar
koher 12-Mar-19 02:36 AM
なるほど。別に統一の機構で表現しなくてもいいか。
Avatar
omochimetaru 12-Mar-19 02:37 AM
よく「これはadditiveだからええんや」って言ってるのはそういう気持ちだと思ってます
Avatar
koher 12-Mar-19 02:37 AM
opaque result type 、 ABI additive でも、標準ライブラリに適用したときに API の互換性がぶっ壊れまくりそう・・・
Avatar
omochimetaru 12-Mar-19 02:38 AM
APIとしてはそもそも破壊的ですね
02:38
もともとLazyMapCollecitonを返してるやつがsome Collectionになってしまうんだから
02:38
let c: LazyMapCollection = xs.lazy.map { ... }
02:38
↑過去にこう書いてたら死ぬ
02:39
そっちの問題はどうなるんでしょうね
02:39
提案の方では議論されてないように見える。
02:39
stdlibはもう塩漬けなのかしら。
Avatar
koher 12-Mar-19 02:39 AM
古いバイナリで標準ライブラリ使ってて、 API 変更されたら OS アップデートで死ぬ?
Avatar
omochimetaru 12-Mar-19 02:39 AM
あいや、いいのか
02:40
古いバイナリ向けには古い形式のstdlibを配布すればよいので、死ななそう。
Avatar
koher 12-Mar-19 02:41 AM
stdlibはもう塩漬けなのかしら。
Proposal のどこかに、 API にとっては破壊的だけどやる価値があるって書いてあった気がする。
Avatar
omochimetaru 12-Mar-19 02:41 AM
APIについてのソースマイグレーションは、自動修正でなんとなく対応して
02:41
バイナリについては昔のstdlibも配布すればいいからなんとかなりそう。
02:42
If opaque result types are retroactively adopted in a library, it would initially break source compatibility (e.g., if types like EnumeratedSequence, FlattenSequence, and JoinedSequence were removed from the public API) but could provide longer-term benefits for both source and ABI stability because fewer details would be exposed to clients.
02:42
ほんとだ、書いてあった。 (edited)
Avatar
omochimetaru 15-Mar-19 08:59 AM
A different, experimental take on property behaviors.
08:59
2016年から無限放置されてたProperty Behavior(SE-0030)に急に動きが。 (edited)
09:00
AST - Semaまで作ってあるっぽい。
09:00
struct Wrapper<T> { var value: T } func testParsing() { let wrapped1: Int by Wrapper let wrapped2: Int by Wrapper = Wrapper(value: 5) let wrapped3 by Wrapper = Wrapper(value: 5) _ = wrapped1 _ = wrapped2 _ = wrapped3 }
09:01
Kotlinみたいに型の後ろにby句を与えるスタイルっぽい
09:02
func testSuppressUnwrap() { var wrapped1 by WrapperWithInitialValue = 5 let z = ^wrapped1 }
09:02
謎のキャレットオペレータ
Avatar
koher 15-Mar-19 09:25 AM
話を戻してしまうけど、 Joe Groff の↓の Chris Lattner への反論、めちゃくちゃおもしろいこと言ってる気がする。 https://forums.swift.org/t/se-0244-opaque-result-types/21252/69 読み違えなければ、 Rust では existential type を記述するときに( Swift と違って)明示的に dyn キーワードを付けるようにするという決定が下されて、 Swift での過去の議論では同様のキーワードとして any が議論されていた。そして、そうなれば、 any Foo は existential type に、 some Foo は opaque type になると見越している?
Indeed, this is pretty much what opaque types boil down to, is the ability for a function to "output" generic parameters in addition to taking them as inputs. Another way we could conceivably notate this is by putting the output parameters after the ->, as a number of people ...
Avatar
omochimetaru 15-Mar-19 09:29 AM
someキーワードが 、ExistentialをAnyHogehogeとして慣習的に使ってる事の対としてキレイって意見自体は、someの打診をしたスレで言ってた気がする
09:30
このレスでは、Generalized Existential Typeを Any<P0> とか any P0 で書けるような文法が将来的に産まれたときうまいこといくというメリットも見据えてるよ、って補足かな?
Avatar
koher 15-Mar-19 09:44 AM
any Foosome Foo すごくキレイだと思うんだけど、それなら top type と bottom type も Ceylon みたいに AnythingNothing だったらキレイだったのになぁ。
09:47
これ、英語に合わせる言葉遊びじゃなくて、英語の any, some, no の概念が良くできてるということな気がする。
Avatar
omochimetaru 15-Mar-19 09:50 AM
AnyとNeverの方がオシャレな感じがします
09:51
-thingだと1単語だけど2語みたいな感じだからゴツイ
Avatar
koher 15-Mar-19 09:55 AM
その感覚は理解できるけど、 Nothing の方が bottom type の本質を表している気がする。そして Nothing の対比としては Anything だろうなと。
09:56
Kotlin は AnyNothing だし、 Any は top type じゃなくて Any? が top とかグダグダ。
09:57
AnyNone とかでもいいのかもだけど、 AnyNone が対として自然なのかわからない・・・。
Avatar
omochimetaru 15-Mar-19 09:57 AM
たしかにCeylonのやつが理論的にスキがないのはわかります
09:58
Noneはoptionalで使っちゃったし、someの意味がここに来て2つ出来ちゃったのはしんどいですね
Avatar
koher 15-Mar-19 09:59 AM
まあ Optionalsome はほぼ使うことがないからいいんじゃないかな?
09:59
別に .some はキーワードじゃなくてただの enumcase だし。言語の一部ではない。
Avatar
omochimetaru 15-Mar-19 10:00 AM
厳密にはそうすね
Avatar
koher 15-Mar-19 10:01 AM
パターンマッチにしても
if case let .some(foo) = foo { ... }
if case let foo? = foo { ... }
みたいなシュガーが用意されてるから、 Optional.some を使うケースってほぼない気がする。
Avatar
omochimetaru 18-Mar-19 07:19 AM
ORTスレ、クリスラトナーが、全く異なるアプローチ?のドラフトを投稿して、会話が伸びてる https://forums.swift.org/t/se-0244-opaque-result-types/21252/119?u=omochimetaru
Ok, here is a draft of the document, please take a look. In comparison to the proposal outlined here, this approach requires no new keywords or grammar productions (just adds a decl modifier, and undisables an existing grammar production in type aliases), it composes properl...
07:20
opaque public typealias CertainMutableCollection<T> : MutableCollection & RangeReplaceableCollection = [T]
(edited)
07:20
こうやると、名前だけモジュール外にexposeできる、というアイデア。
07:21
現状だと、internalな型は、publicなfuncの返り値はできないから、publicな型にして露出させちゃうけど、
07:21
名前だけpublicにするって仕組み
Avatar
omochimetaru 18-Mar-19 07:41 AM
Paulさんのこの文うける
Two of my tried and true Swift heuristics are “Joe Groff knows best” and “Chris Lattner knows best,” and these competing proposals put them in conflict!
Avatar
tarunon 18-Mar-19 07:41 AM
ワロタ
Avatar
omochimetaru 18-Mar-19 07:51 AM
ラトナーが結構厳しい事言ってるなあ
07:53
「このプロポーザルの第一の目的はAPI詳細隠蔽、Rustのimpl Traitはこの目的とはゴールが違う、彼らはstable ABIを気にしてないので世界が違う、ORTは過剰に複雑で侵略的な機能で、多くの技術的負債とコンパイラの複雑さをもたらすだろう」 (edited)
Avatar
omochimetaru 18-Mar-19 08:31 AM
既存のExistential型を禁止して、anyキーワードをつけないといけないようにすると、綺麗になりそうだなあ
08:32
<T: P>(T)と(P)の違いはわかりにくいけど、<T: P>(T)と(any P)ならわかりやすいと思うし、 前者が (some T) になれば (some T)と(any T)が違うものだと明らか
Avatar
koher 18-Mar-19 09:16 AM
@omochimetaru そうなんよねー。 any Foosome Foo だとめちゃくちゃキレイ。 https://forums.swift.org/t/se-0244-opaque-result-types/21252/140
It seems so beautiful. // generics func useAnimal( animal: A) { /* ... */ } // opaque argument types (sugar of ^) func useAnimal( animal: some Animal) { /* ... / } // existential (argument) types func useAnimal(_ animal: any Animal) { / ... */ } // "reverse generics" fu...
Avatar
tarunon 18-Mar-19 09:29 AM
anyとsomeは好きですねぇ
Avatar
koher 18-Mar-19 09:32 AM
Existentialに明示的にキーワード付けないといけなくするのも濫用を防げそうでいいですよね。インタフェース感覚で使われることを防止する効果もありそう。
09:36
フォーラムのスレッド見てても ORT の概念に混乱してる人多そうだし、 ORTの前に reverse generics を提案した方が良かったのかな。
Avatar
norio_nomura 19-Mar-19 10:18 AM
PR のブランチをチェックアウトしてコンパイラをビルドすれば…
CIによってビルドされたmacOS用toolchainがPRのコメントに載っているので、それをダウンロードすれば自分でビルドしなくても試せます。 コメント: https://github.com/apple/swift/pull/21137#issuecomment-468118328 toolchain: https://ci.swift.org/job/swift-PR-toolchain-osx/216//artifact/branch-master/swift-PR-21137-216-osx.tar.gz
(edited)
WIP towards a prototype of an MVP subset of https://forums.swift.org/t/opaque-result-types/15645 . For an initial implementation, this won't include the resilience, second-order where constrain...
🙏 1
Avatar
koher 19-Mar-19 12:18 PM
いただいたコメントを追記しておきました。
👍 1
Avatar
omochimetaru 20-Mar-19 12:39 AM
The review of SE-0250: Swift Code Style Guidelines and Formatter begins now and runs through April 10, 2019. The proposal is written by @allevato and @dabrahams. Please note that there has been significant discussion already on the pitch thread. The Core Team will incorpor...
00:40
スタイルガイドのレビューだ。どんどん来るな。
Avatar
omochimetaru 20-Mar-19 12:57 AM
このプロポーザルは公式スタイルガイドとフォーマットツールをSwiftプロジェクトに取り込むことを決めるだけで、 スタイルそれ自体はこれが通ったあとで別のプロポーザルでやっていくと
Avatar
tarunon 20-Mar-19 04:43 PM
フォーマッタ欲しいよね
Avatar
omochimetaru 21-Mar-19 12:21 AM
このレビュー4/10までやっててだいぶ長い
Avatar
koher 21-Mar-19 02:54 AM
レビュー期間ってどういう風に決められてるんだろ?内容からCore TeamかReview Managerが決めてるのかな?
Avatar
omochimetaru 21-Mar-19 02:59 AM
そう思う SEプロセスの説明のとこに書いてあるかも?
Avatar
koher 21-Mar-19 09:10 AM
reverse generics を提供してる言語ってあるかな?
Avatar
koher 22-Mar-19 09:52 AM
↓と同じことって opaque type alias ならできるけど opaque result type ではできなくない?
func makeAnimals() -> <A: Animal> (A, A) { return (Cat(), Cat()) }
(edited)
09:53
// opaque type alias opaque typealias A: Animal = Cat func makeAnimals() -> (A, A) { return (Cat(), Cat()) }
09:54
opaque type alias って reverse generics と等価(単に面倒な構文なだけ)な気がするんだけどそんなことない? (edited)
Avatar
norio_nomura 26-Mar-19 02:22 PM
Xcode 10.2のSwift 5.0と https://swift.org/download/ からダウンロードした swift-5.0-RELEASE とで、SourceKitのレスポンスが違う…
Swift is a general-purpose programming language built using a modern approach to safety, performance, and software design patterns.
🤔 2
Avatar
norio_nomura 26-Mar-19 02:33 PM
Xcode 10.2はGitHubで公開されてるコミットに追従できていない疑いがある。
Avatar
rintaro 26-Mar-19 03:02 PM
@norio_nomura 詳細知りたいです。
15:04
これで、DocInfoTests.testDocInfoRequest()の結果がXcode 10.2と https://swift.org/download/ からダウンロードしたものの結果が違うのです。
Swift is a general-purpose programming language built using a modern approach to safety, performance, and software design patterns.
Avatar
rintaro 26-Mar-19 03:05 PM
ありがとうございます。見てみますー。
Avatar
norio_nomura 26-Mar-19 03:06 PM
PRはXcode 10.2の出力を前提に書かれてるので、チェックアウトして
$ xcrun --toolchain org.swift.5020190325a swift test --filter testDocInfoRequest
で再現できます。
(edited)
Avatar
rintaro 26-Mar-19 05:00 PM
現象自体は確認できました。もし可能であれば単体のテストケース作って bugs.swift.org にいただけるとありがたいです。
Avatar
norio_nomura 26-Mar-19 11:15 PM
Homebrewで配布しているsourcekittenを使ったテストでも良いですか?
Avatar
rintaro 26-Mar-19 11:24 PM
ぜんぜん大丈夫です
Avatar
norio_nomura 26-Mar-19 11:36 PM
23:37
JIRAはいつになったら絵文字使えるようになるのだろう。
Avatar
rintaro 26-Mar-19 11:39 PM
ありがとうございます!
Avatar
norio_nomura 26-Mar-19 11:40 PM
マルチラインドキュメンテーションコメントの、末尾が違うみたいです。
key.request: source.request.docinfo key.sourcetext: " /** Multiple line commented function. **/ func multiLineCommentedFunc() { } "
Avatar
rintaro 26-Mar-19 11:40 PM
* が普通の文字列として判定されるか、リストの bullet として判定されるかの差異ですね。 (edited)
Avatar
norio_nomura 26-Mar-19 11:43 PM
なるほど。
Avatar
norio_nomura 26-Mar-19 11:55 PM
SourceKittenで各バージョンのSwiftが返す値をテストして来ましたが、Xcodeと https://swift.org/download/ のツールチェインで結果が違うというのは初めて遭遇したかな。
Swift is a general-purpose programming language built using a modern approach to safety, performance, and software design patterns.
Avatar
rintaro 27-Mar-19 12:59 AM
JIRA にコメントされてますが、 - CommonMark に10.2と5.0-RELEASEで差異がある - 10.2の方が新しいCommonMarkであり、本来は5.0-RELEASEも10.2と同じ動作をすべき - リリースのミス。5.1では同じ間違いをしないようにします
Avatar
norio_nomura 27-Mar-19 02:52 AM
ありがとうございます。把握してもらえて安心しました。
Avatar
omochimetaru 27-Mar-19 04:22 AM
cmarkの差なのか、なるほどすごいコーナー
Avatar
omochimetaru 28-Mar-19 10:30 PM
The review of SE-0249 has concluded and the proposal has been accpted:
22:30
キーパスが関数になった
Avatar
tarunon 28-Mar-19 10:31 PM
おおー
Avatar
omochimetaru 28-Mar-19 10:32 PM
今後のオシャレテク
Avatar
tarunon 28-Mar-19 11:13 PM
これはいいね
Avatar
koher 29-Mar-19 12:41 AM
↓これはできない?
let bar: Bar = \Foo.bar(foo)
(edited)
Avatar
tarunon 29-Mar-19 12:41 AM
どうでしょう
Avatar
rintaro 29-Mar-19 12:42 AM
それはできないですね。それだと func bar(_: Foo) メソッドを呼び出す keyPath になってしまう。
Avatar
koher 29-Mar-19 12:43 AM
ああ、カッコをつけるとどうでしょう?
Avatar
rintaro 29-Mar-19 12:44 AM
(\Foo.bar)(foo) どうでしょう。
Avatar
koher 29-Mar-19 12:46 AM
↓はできるみたいですけどどこまでできるんでしょうね。
let bar = (\Foo.bar as (Foo) -> Bar)(foo)
Avatar
omochimetaru 29-Mar-19 12:48 AM
メソッドを呼び出す keyPath になってしまう
なるほどw
Avatar
koher 29-Mar-19 12:51 AM
(foo)let bar: Bar から (Foo) -> Bar を期待していると解釈してくれれば let bar: Bar = (\Foo.bar)(foo) でも通る可能性あるかな?さすがにきついかな…。
Avatar
vicktorManuel 02-Apr-19 12:38 AM
Avatar
kateinoigakukun 04-Apr-19 04:27 AM
Avatar
norio_nomura 10-Apr-19 12:27 AM
The review of SE-0257: Eliding commas from multiline expression lists begins now and runs through April 18, 2019. The proposal is written by @nate_chandler and @anandabits. Reviews are an important part of the Swift evolution process. All review feedback should be either on...
Avatar
omochimetaru 10-Apr-19 12:40 AM
提案にも書かれてる、次の行とつながるパターンとの兼ね合いが不安
Avatar
rintaro 10-Apr-19 12:42 AM
基本的には , 無い場合は普通のfunc ボディ内に書いたのと同じルールで分割されるので、ルール上の問題はないのですが、
00:43
_ = [ "foo": foo .method() "bar": baz ]
こういうのはつらい。<コーディング規約で禁止するしかない。
(edited)
Avatar
omochimetaru 10-Apr-19 12:44 AM
fooのメソッドなのか、そこの型コンテキストに対するドット式なのか曖昧?
Avatar
rintaro 10-Apr-19 12:44 AM
ですね。
00:46
func test() { foo .method() bar }
func test() { foo.method(); bar; }
であり、そのルールで動くので、上に書いた例でも問題はなくパースできるのですが、リーダビリティ的には止めて欲しいっていう意味です。
(edited)
Avatar
omochimetaru 10-Apr-19 12:51 AM
そのケースに限って言えばフォーマッタが.methodの行を1段下げてくれれば問題なさそうだなあ
00:52
揃ってる状況だと人間が先読みしないとパースできないのでつらいけど。
Avatar
omochimetaru 10-Apr-19 08:27 AM
let solutions = [ 2*(1-sqrt(a))*sqrt(b+sqrt(b)) -(1+sqrt(a))(sqrt(2*b)-sqrt(2)) ] // two solutions let solutions = [ 2*(1-sqrt(a))*sqrt(b+sqrt(b)) - (1+sqrt(a))(sqrt(2*b)-sqrt(2)) ] // one solution
08:28
厳しい
Avatar
norio_nomura 11-Apr-19 12:48 AM
docker image作った。
$ docker run --privileged -it -v `pwd`:`pwd` -w `pwd` --rm norionomura/swift:pr-22714 swift Welcome to Swift version 5.0-dev (LLVM 771292f12a, Swift 474d293b05). Type :help for assistance. 1> print( 2. "hello" 3. "world" 4. ) hello world
Avatar
omochimetaru 15-Apr-19 01:50 AM
A pitch to make some ABI annotations used in the standard library available to all Swift users. Proposal PR here Introduction One of Swift's goals is to be a good language for libraries with binary compatibility concerns, such as those shipped as part of Apple's OSs. This i...
01:51
アプリをリビルドせずにライブラリのバイナリをアップデートできるようになるLibrary evolutionのピッチ
01:52
すでに標準ライブラリで実現されていることを、ユーザに解放する。 コンパイル時にevolutionモードでビルドする選択肢が与えられることと、内部オプションだったflozenが公式になる。
Avatar
tarunon 15-Apr-19 01:53 AM
これはswiftだけの問題なのかな?appstoreのポリシーもあるのでは (edited)
Avatar
omochimetaru 15-Apr-19 01:53 AM
iOSアプリの場合、開発時点での第三者ライブラリを配布できるだけで
01:54
AppStoreから配信されたアプリの内部のライブラリをアップデートすることはないんじゃないかな。
01:54
たとえば、今はCarthageではみんなが手元でコンパイルしてるけど、最初からビルドしておいたバイナリを配布するようにするとか。 (edited)
01:57
他の言語と比べると、値型のフィールドを追加できるのが面白いと思った。 スタックにメモリ確保するときにメタタイプからサイズを取ってくるのでそこが動的になってる。
01:58
その方法なら値型のデータ自体はスタックに置き続けることができる。
Avatar
t.ae 16-Apr-19 08:11 AM
inlinableってジェネリクスのspecializeもやってくれると思ってたんですがやってくれないんでしょうか? https://github.com/t-ae/inlinable-performance/blob/master/Sources/inlinable-performance/inlinable_performance.swift
public func matmul_base<T: Numeric>(lhs: [T], rhs: [T], m: Int, n: Int, p: Int) -> [T] { return matmul_internal(lhs: lhs, rhs: rhs, m: m, n: n, p: p) } @inlinable public func matmul_inlinable<T: Numeric>(lhs: [T], rhs: [T], m: Int, n: Int, p: Int) -> [T] { return matmul_internal(lhs: lhs, rhs: rhs, m: m, n: n, p: p) } public func matmul_specialize(lhs: [Double], rhs: [Double], m: Int, n: Int, p: Int) -> [Double] { return matmul_internal(lhs: lhs, rhs: rhs, m: m, n: n, p: p) }
以上のように内部実装は共通でインターフェースだけ違うのを計測してみると、 https://github.com/t-ae/inlinable-performance/blob/master/Tests/inlinable-performanceTests/inlinable_performanceTests.swift
Test Case '-[inlinable_performanceTests.inlinable_performanceTests testBase]' passed (11.864 seconds). Test Case '-[inlinable_performanceTests.inlinable_performanceTests testInlinable]' passed (11.498 seconds). Test Case '-[inlinable_performanceTests.inlinable_performanceTests testSpecialize]' passed (0.340 seconds).
と素のものとinlinableで同程度になっています。 インライン化と同時にじゃないとspecializeされないってのがありそうかなーと思っています。
Contribute to t-ae/inlinable-performance development by creating an account on GitHub.
Contribute to t-ae/inlinable-performance development by creating an account on GitHub.
Avatar
omochimetaru 16-Apr-19 08:12 AM
速度で判別するよりIRを見たほうが良いと思います
Avatar
koher 16-Apr-19 08:12 AM
swift test -c release で計測してる?
Avatar
t.ae 16-Apr-19 08:12 AM
@koher もちろんです。
08:13
@omochimetaru モジュール跨ぎはやったこと無いので調べながらやってみます……
Avatar
koher 16-Apr-19 08:15 AM
Avatar
t.ae 16-Apr-19 08:17 AM
お、そんな便利なのが。>save-optimization-record (edited)
Avatar
omochimetaru 16-Apr-19 08:18 AM
ちゃんと試してないけど -emit-module でモジュール作って、 -Iでインポート とかな気がする
Avatar
t.ae 16-Apr-19 08:22 AM
--- !Passed Pass: sil-generic-specializer Name: sil.Specialized DebugLoc: File: /Users/araki/Desktop/t-ae/inlinable-performance/Tests/inlinable-performanceTests/inlinable_performanceTests.swift Line: 30 Column: 26 Function: 'closure #1 in inlinable_performanceTests.testInlinable()' Args: - String: 'Specialized function ' - Function: '"inlinable_performance.matmul_inlinable<A>(lhs:rhs:m:n:p:)"' - String: ' with type ' - FuncType: '(@guaranteed Array<Double>, @guaranteed Array<Double>, Int, Int, Int) -> @owned Array<Double>' ...
うーん?
Avatar
omochimetaru 16-Apr-19 08:24 AM
<A> => [Double] でされてるね
Avatar
t.ae 16-Apr-19 08:25 AM
--- !Missed Pass: sil-generic-specializer Name: sil.NoDef DebugLoc: File: /Users/araki/Desktop/t-ae/inlinable-performance/Tests/inlinable-performanceTests/inlinable_performanceTests.swift Line: 31 Column: 13 Function: 'closure #1 in inlinable_performanceTests.testInlinable()' Args: - String: 'Unable to specialize generic function ' - Callee: '"XCTest.XCTAssertEqual<A>(_:_:_:file:line:)"' - String: ' since definition is not visible' ...
呼び出し側がミスしてる?
08:27
いやこれはXCTAssertEqualのログだ
08:32
// matmul_inlinable<A>(lhs:rhs:m:n:p:) sil [serialized] @$s21inlinable_performance07matmul_A03lhs3rhs1m1n1pSayxGAH_AHS3itSjRzlF : $@convention(thin) <τ_0_0 where τ_0_0 : Numeric> (@guaranteed Array<τ_0_0>, @guaranteed Array<τ_0_0>, Int, Int, Int) -> @owned Array<τ_0_0> // matmul_specialize(lhs:rhs:m:n:p:) sil @$s21inlinable_performance17matmul_specialize3lhs3rhs1m1n1pSaySdGAH_AHS3itF : $@convention(thin) (@guaranteed Array<Double>, @guaranteed Array<Double>, Int, Int, Int) -> @owned Array<Double>
SIL的にはinlinableはジェネリックなままみえてそうですね
Avatar
omochimetaru 16-Apr-19 08:50 AM
最適化されるとspecializeされたSILができる
08:50
SIL生成直後はまだジェネリックしかない
Avatar
t.ae 16-Apr-19 08:58 AM
ああ、-Oつけわすれてました。 つけるとmatmul_inlinableが消える代わりにmatmul_internalがジェネリックなまま出てきますね。
08:58
どうやら@usableFromInlineなジェネリックメソッドを@inlinableなメソッドでspecialize出来ていないぽい。
まさにこれに該当しそうです。
😂 1
Avatar
omochimetaru 17-Apr-19 12:55 AM
matmul_internalはusableFtomInlineが付いてるの?
Avatar
t.ae 17-Apr-19 12:56 AM
付いてますよ。ついてないとinlinableから呼べないです。
Avatar
omochimetaru 17-Apr-19 12:58 AM
usableFtomInlineは
00:58
inlineableから呼ばれてても良い つまり実態としてはABI publicだけど APIとしては外から呼べない
00:59
って用途だったから、展開されたinlineableの中からは、ただの呼び出しとして維持されるので、正しい気がする
00:59
呼べるだけで中身はpublicじゃないから更なるインライン展開やスペシャライズはできない
01:00
matmul_specializeの方は
01:00
モジュールをビルドする時点で展開されるから
01:00
動いてる
Avatar
t.ae 17-Apr-19 01:01 AM
matmul_specializeについてはそうでしょうね。 (edited)
Avatar
omochimetaru 17-Apr-19 01:02 AM
inlineable を指定するとSILコードが外に晒されるから最適化できる
01:02
usableFromInlineは関数ヘッダーが見えるだけだと思う
Avatar
t.ae 17-Apr-19 01:03 AM
あれ?internalもinlinableにできるんでしたっけ……
01:03
そもそも認識が間違っていた可能性が
Avatar
omochimetaru 17-Apr-19 01:03 AM
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
Avatar
t.ae 17-Apr-19 01:04 AM
@usableFromInlineから@inlinableにしたらたしかにインライン化されました。
Avatar
omochimetaru 17-Apr-19 01:05 AM
The attribute can only be applied to declarations with public or internal visibility.
Avatar
t.ae 17-Apr-19 01:06 AM
inlinable privateだと
'@inlinable' attribute can only be applied to public declarations, but 'matmul_internal' is private
なるメッセージが出るのでpublic onlyと誤解した可能性が高そうです。
Avatar
omochimetaru 17-Apr-19 01:06 AM
internalでもinlinableにできんのか。
01:06
それは知らなかった。
01:08
たしかにそのエラーメッセージはわかりにくい
01:08
bugsにチケット出したら?すでにありそうな気もする
Avatar
t.ae 17-Apr-19 01:09 AM
エラーメッセージ修正だけならPR出してコントリビューターになるチャンスも (edited)
01:10
https://bugs.swift.org/browse/SR-8212 すでにありました。
Avatar
omochimetaru 17-Apr-19 01:12 AM
パッチ作るの簡単そう
Avatar
t.ae 17-Apr-19 01:12 AM
むしろメッセージの内容のほうが難しそうですね
01:12
コメントでその件で話してるみたいです。
Avatar
omochimetaru 17-Apr-19 01:14 AM
メッセージ内容というか
01:15
メソッドがinternal + inlineableでもクラスがinternal + usableFromInlineじゃないと
01:15
いけないから
01:15
「inlineableはpublic or internalにしかつけられません」は偽って事だよね
Avatar
t.ae 17-Apr-19 01:16 AM
クラスがusableFromInlineじゃなくてもコンパイルは通るみたいです。 でインライン化はされないんだと思います。
Avatar
omochimetaru 17-Apr-19 01:17 AM
Slavaのサンプルコードが間違ってる?
Avatar
t.ae 17-Apr-19 01:17 AM
class C { @inlinable func f() {} // error }
ここでerrorって言ってるのは少なくともコンパイルエラーのことではなさそう
Avatar
omochimetaru 17-Apr-19 01:17 AM
もしコンパイルが通るとすれば
01:17
それはそれでかなりわかりにくい、なぜかインライン化されない現象が
01:17
生じる事になるが・・・
Avatar
t.ae 17-Apr-19 01:18 AM
@inlinable public func x() { let c = C() c.f() }
Class 'C' is internal and cannot be referenced from an '@inlinable' function
結局CがusableFromInlineじゃないと他のところでコンパイルが通らないですね。
01:19
それを指してerrorと書いてるのか
Avatar
omochimetaru 17-Apr-19 01:19 AM
それはメソッドfが無関係じゃない?
Avatar
t.ae 17-Apr-19 01:19 AM
まぁそうなんですが
Avatar
omochimetaru 17-Apr-19 01:20 AM
「inlineableにならない」ではないか?
01:20
「通常inlineableはusableFromInlineも暗黙に与えるが、それはouter scopeがusableFromInlineの場合に限る」 (edited)
01:21
だから、 「C.fが、inlineableではあるが、usableFromInlineではない」状態が発生するんじゃない?
Avatar
t.ae 17-Apr-19 01:32 AM
inlinableだけどusabeFromInlineじゃない状態をerrorと呼んでるというのが合ってそうですかね。inlinableだけど決してインライン化されないという実装者の意図に反した状態で。
Avatar
omochimetaru 17-Apr-19 01:32 AM
かなあ。「決して」が確証がない、なんかやりようがあるんかな。
01:32
あと、「実装者の意図」が、モジュール外だった場合にってことだよね。 (edited)
Avatar
t.ae 17-Apr-19 01:33 AM
モジュール内でinlinableないとインライン化されないケースってなんかあります?
Avatar
omochimetaru 17-Apr-19 01:33 AM
[omochi@omochi-iMac-PC43 mdi]$ swiftc -emit-module m.swift [omochi@omochi-iMac-PC43 mdi]$ swiftc -silgen -I . a.swift
↑これでコンパイルできたけど、実行ができない。
Avatar
t.ae 17-Apr-19 01:33 AM
僕の方はFrameworkつくって-Fで与えました。
Avatar
omochimetaru 17-Apr-19 01:34 AM
モジュール内は常に全部inlineableか?
01:34
inlineableは外向けの影響しかないか。
01:34
内向けでヒントしたりするのは @inline(always) とかか。
Avatar
t.ae 17-Apr-19 01:34 AM
ですね。
Avatar
omochimetaru 17-Apr-19 01:35 AM
僕の方はFrameworkつくって
どうやるの?
Avatar
t.ae 17-Apr-19 01:35 AM
上に貼ったプロジェクトがSPMなんでxcodeprojからビルドした生成物を使いました。
Avatar
omochimetaru 17-Apr-19 01:35 AM
ああ、なるほど・・・
01:41
少し進んだ
01:42
inlineableだけどusableFromInlineじゃない状態って意義あるのかな
01:42
ないんだとすれば、その時点でエラーにしてやったほうがよさそうだ
Avatar
t.ae 17-Apr-19 01:42 AM
ちょっと思いつかないですよね。
Avatar
omochimetaru 17-Apr-19 01:43 AM
で、「メソッドをinlineableにするにはクラス本体をusableFromInlineにしてください」って
01:43
エラーメッセージを出す仕組みが別途あればいい?
Avatar
t.ae 17-Apr-19 01:43 AM
それがベストだと思います。
Avatar
omochimetaru 17-Apr-19 01:44 AM
このスレッドで聞いてみるか
Avatar
t.ae 17-Apr-19 01:44 AM
mark outer scope as @usableFromInline or make outer scope publicですかね
Avatar
omochimetaru 17-Apr-19 01:44 AM
俺でもいいけど書き込む?
Avatar
t.ae 17-Apr-19 01:44 AM
特にこだわりないんでお願いします。
Avatar
omochimetaru 17-Apr-19 01:44 AM
OK
Avatar
omochimetaru 17-Apr-19 01:53 AM
かきこんどいた
🙏 1
01:57
コンパイルできたけどlibSwiftCoreが無いって言われてしまう
01:57
LC_RPATHが指定できれば良さそう
02:00
お、できた
02:04
$ swiftc -parse-as-library -emit-object m.swift $ swiftc -emit-module m.swift $ swiftc -I . a.swift m.o -Xlinker -rpath -Xlinker /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx $ ./main
Avatar
norio_nomura 17-Apr-19 02:28 AM
呼べるだけで中身はpublicじゃないから更なるインライン展開やスペシャライズはできない
なるほど、そういう事か。
Avatar
omochimetaru 17-Apr-19 02:28 AM
これもできた
$ swiftc -emit-library m.swift $ swiftc -L . -lm -I . a.swift -Xlinker -rpath -Xlinker /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx $ ./a
02:29
@norio_nomura usableFromInlineはそうやって本体のバイナリ公開を抑制することで後のバイナリアップデートに備えるための指定子っぽいですね。
Avatar
norio_nomura 17-Apr-19 02:32 AM
A pitch to make some ABI annotations used in the standard library available to all Swift users. Proposal PR here Introduction One of Swift's goals is to be a good language for libraries with binary compatibility concerns, such as those shipped as part of Apple's OSs. This i...
Avatar
omochimetaru 17-Apr-19 02:32 AM
はい。SE0192のproposalの時点でmotivationに > Implementing support for library evolution ...
02:32
って記述があるのにさっき気がついた。
02:33
ABI長期計画ちゃんとつながっててえらい
Avatar
norio_nomura 17-Apr-19 02:37 AM
ジェネリックメソッドを@inlinableにした場合、内部で使っているジェネリックメソッドも@inlinableにしておかないと、@_specializeを使わない限り完全にはspecializeされないって事だよね。これは悩ましいな。 (edited)
Avatar
omochimetaru 17-Apr-19 02:39 AM
内部のメソッドを @inlinable internal にするのがやりたいことではないです? (edited)
Avatar
norio_nomura 17-Apr-19 02:43 AM
@inlinable internalなメソッドを変更した場合、ABIが変わるって事だよね。
Avatar
omochimetaru 17-Apr-19 02:43 AM
そうですね。バイナリ互換性は保てない。
02:44
インライン化してほしい=利用側にコードを埋め込みたい、ということだから、このジレンマはどうしようもない。
02:45
バイナリだけアップデートしたとき、すでに埋め込まれたコードは差し替わらないので。
Avatar
norio_nomura 17-Apr-19 02:46 AM
じゃあ、ABIを維持するためにジェネリックメソッドを@usableFromInline internalにすると、今度はそれを@inlinableから使った場合に遅くなってしまう。
02:47
結果、何も考えずに@inlinableを付けただけだと遅くなる場合がある。
Avatar
omochimetaru 17-Apr-19 02:48 AM
inlinableな関数gが非ジェネリックで、内部の関数fがジェネリックなとき、そうなりますね。
02:49
inlinableな関数gもジェネリックパラメータを持っていて、それをfに転送しているだけの場合は、inlienableをつけなかったとしても結果は同じだけど、
02:49
gが非ジェネリックな場合は、gの中から呼び出すfが専用に最適化されるから、inline化しないほうが良いって事に。
02:50
あ、でも、そういうケースは
02:50
fの @_specialize(T = Int) の使いどころか?
02:51
fのスペシャライズ版が生成され、かつ、存在が明示的になるから、gからf<Int> が呼ばれるようになって、 その特殊化版を呼ぶgが、利用側でインライン化されるなら
02:51
遅くならない。 そこまで理解してないと遅くなっちゃう可能性があるのはそうですね。
Avatar
norio_nomura 17-Apr-19 02:53 AM
んー、以前試した時は、gがジェネリックな場合はfとgの両方に@_specialize を付けないとダメだった気がする。
Avatar
omochimetaru 17-Apr-19 02:54 AM
gがジェネリックな場合はそうなると思います。
02:55
func gGeneric<T>(_ x: T) { f(x) } func gInt(x: Int){ f(x) } func f<T>(_ x: T) { ... }
Avatar
norio_nomura 17-Apr-19 02:57 AM
@_specializeがもっと書きやすければいいのだけど。 ジェネリックパラメータが多いと大変。
extension StringProtocol { @usableFromInline @_specialize(where Self == String, S == String, T == String) @_specialize(where Self == String, S == String, T == Substring) @_specialize(where Self == String, S == Substring, T == String) @_specialize(where Self == String, S == Substring, T == Substring) @_specialize(where Self == Substring, S == String, T == String) @_specialize(where Self == Substring, S == String, T == Substring) @_specialize(where Self == Substring, S == Substring, T == String) @_specialize(where Self == Substring, S == Substring, T == Substring) …
(edited)
Avatar
omochimetaru 17-Apr-19 02:57 AM
gGeneric = inlinable : ジェネリックなfを呼び出すgGeneric が展開されるだけ、遅い gInt そのまま : gInt 内部に 特殊化された f の呼び出しが展開される、早い gInt = inlineable : ジェネリックなfを呼び出す gInt が展開されるだけ、遅い gInt = inleinable + f specialized(Int): Intに特殊化された f を呼び出すgInt が展開される、早い ( このパターンが僕の仮説)
02:58
gGeneric = inlineable + f specialized(Int) : Intに特殊化されたfは生成されるけど、gGenericから呼び出すf はジェネリックT な fにすぎないので、遅い
02:59
gGeneric specialized(Int) : Int に特殊化されたgが生成されて、その中で f が特殊化されるので早い gGeneric specialized(Int) + inlineable : Int に特殊化されたgが生成されるけど f はジェネリックなので ジェネリックな f の呼び出しが展開されるだけで遅い
03:00
gGeneric specialized(Int) inlinable + f specialized (Int) : Int に特殊化されたgとIntに特殊化されたfがあるので展開されて早い
03:00
String / Substring x Self / S / T で 2^3 = 8 通りあるんですか・・・
03:01
Specializeに組み合わせ表記があったら嬉しいですね
03:01
@_specialize(where Self == String x Substring, S == String x Substring , T == String x Substring) (edited)
03:01
↑これで8通りを書き並べたのと同じになる
Avatar
norio_nomura 17-Apr-19 03:06 AM
gInt = inleinable + f specialized(Int): Intに特殊化された f を呼び出すgInt が展開される、早い ( このパターンが僕の仮説)
これはこの通りだった気がする。
Avatar
omochimetaru 17-Apr-19 03:09 AM
なるほど。そこで f に specialized を付けないと遅くなっちゃうってのは たしかに↓のとおりですね >何も考えずに@inlinableを付けただけだと遅くなる場合がある。
Avatar
norio_nomura 17-Apr-19 03:26 AM
また@inlinable周りは検証し直さないといけないな。 (edited)
Avatar
omochimetaru 17-Apr-19 03:36 AM
SwiftPMのビルドを調べてるけど、SwiftPMは一発でswiftmoduleとobject(*.swift.o)を生成してるっぽいんだけど、コマンドを真似しても再現できない・・・
Avatar
omochimetaru 17-Apr-19 03:55 AM
ああああ・・・・ (edited)
03:56
フルパスで与えないとoutput-file-mapとマッチングしねえのか・・・
Avatar
omochimetaru 17-Apr-19 04:07 AM
{ "": { }, "/Users/omochi/temp/mdi/m.swift": { "object": "/Users/omochi/temp/mdi/b/m.swift.o" } }
#!/usr/bin/env ruby require "shellwords" cmd = [ "swiftc", "-emit-dependencies", "-emit-module", "-emit-module-path", "b/m.swiftmodule", "-output-file-map", "map.json", "-parse-as-library", "-emit-object", "/Users/omochi/temp/mdi/m.swift" ] system(cmd.shelljoin)
(edited)
04:08
これで .o と .swiftmodule を一発で作れた。
Avatar
koher 17-Apr-19 11:30 AM
Joe_Groff I have (belatedly) generated a new toolchain with the latest implementation of the feature, which also supports the ABI resilience aspects of the proposal, and uses the proposed some P syntax:
https://forums.swift.org/t/se-0244-opaque-result-types-reopened/22942/52
I have (belatedly) generated a new toolchain with the latest implementation of the feature, which also supports the ABI resilience aspects of the proposal, and uses the proposed some P syntax:
04:39
早くない?
04:39
いつもレビュー期間終わって結構長い間そのままなのに。
Avatar
omochimetaru 18-Apr-19 04:39 AM
はやっ
04:40
しかもコメントがなにもない
04:40
SE-0244 has been accepted.
04:40
いや、レビュースレッドの末尾に書いてあるのか
04:41
Several reviewers felt that being able to name opaque types is an important feature for many use cases. This is clearly a useful feature and would be a good next step, but the core team thinks that the feature as proposed consists of a reasonable "minimum viable product" to land now, and then can be added to through subsequent proposals.
Avatar
koher 18-Apr-19 04:42 AM
昨日までレビュー期間で西海岸時間だから、 Core Team の間で結論すでに出ててレビュー期間終わって即 accept されたのかな?
Avatar
omochimetaru 18-Apr-19 04:42 AM
いくらかのレビュワーがOpaqueTypeに名前をつける機能(ReverseGenericsとかでしょうね)を大事って言ってるけど、minimum viable productを出すのが良いと結論した、みたいな。
Avatar
koher 18-Apr-19 04:42 AM
レビュースレッドに Chris Lattner が現れなかったのは、予め話して納得したのかな??
Avatar
omochimetaru 18-Apr-19 04:42 AM
たしかに。
04:42
opaque typealiasで議論になってたのに
04:43
こっちにはこなかったですね。たしか将来的な方向についてまとまってなさすぎるってラトナも指摘してたから
04:43
「 Generics UI Improvements overview」をまとめるときに一緒に話してそう
Avatar
koher 18-Apr-19 04:44 AM
これが accept されたってことは、 existential に any がつくとこまで既定路線なのかな?
Avatar
omochimetaru 18-Apr-19 04:45 AM
基本的にはそうでしょうね、今後プロポーザルが出てきそう
Avatar
koher 18-Apr-19 04:46 AM
March 18, 2019 (final branching): The swift-5.1-branch will have changes merged from master one last time. After the final branch date there will be a “bake” period in which only select, critical fixes will go into the release (via pull requests).
https://swift.org/blog/5-1-release-process/ これ 5.1 に間に合わなかったかな?それとも重要機能で取り入れられる?
(edited)
This post describes the goals, release process, and estimated schedule for Swift 5.1.
Avatar
omochimetaru 18-Apr-19 04:46 AM
Generics Manifestoでも長いこと進まなかったやつとかもあるから、Generics Improvementsのどれがどの順番でどんくらいのペースで進むのかは結構ブレそうだけど
04:47
間に合って無さそうですね
04:47
でもこれまでも滑り込みで機能追加することあった気がする
Avatar
koher 18-Apr-19 04:53 AM
Result とか滑り込みだったっけ?
04:53
Result よりは重要そうだけど、実装も大変そうだから余裕ももって 5.1 は回避されるかもしれないなぁ。
04:53
標準ライブラリの変更とかも考えるときついかな。
Avatar
omochimetaru 18-Apr-19 04:54 AM
いずれにしても、標準ライブラリの型をsomeに書き換える作業が間に合わ無さそう
Avatar
rintaro 18-Apr-19 04:55 AM
標準ライブラリの型をsomeに書き換える
って、プロポーザルに含まれてます?
Avatar
omochimetaru 18-Apr-19 04:55 AM
このプロポーザルには含まれてないですね、そういえばGenerics Improvementsにも書いてないな
Avatar
rintaro 18-Apr-19 04:55 AM
含まれてないなら別プロポーザル必要な気がする。
Avatar
omochimetaru 18-Apr-19 04:55 AM
最初のプロポーザルのMotivationには書いてあったと思うけど
04:56
プロポーザルの内容それ自体に出てきたことは無いです
Avatar
omochimetaru 25-Apr-19 07:40 AM
@swift-5.1.5 swiftc -emit-sil -O
func main() -> Int { let hoge: Int? = 1 let fuga = hoge .map { $0 * 2 } .map { $0 + 3 } .map { $0 * 4 } return fuga ?? 99 } main()
(edited)
Avatar
swift51 BOT 25-Apr-19 07:40 AM
exit status: 2 with stderr:
error: unable to invoke subcommand: /usr/bin/swift-swiftc (No such file or directory)
(edited)
Avatar
omochimetaru 25-Apr-19 07:40 AM
@swift-5.1.5 -help (edited)
Avatar
swift51 BOT 25-Apr-19 07:40 AM
OVERVIEW: Swift compiler USAGE: swift OPTIONS: -assert-config <value> Specify the assert_configuration replacement. Possible values are Debug, Release, Unchecked, DisableReplacement. -continue-building-after-errors Continue building, even after errors are encountered -debug-info-format=<value> Specify the debug info format type to either 'dwarf' or 'codeview' -debug-info-store-invocation Emit the compiler invocation in the debug info. -debug-prefix-map <value> Remap source paths in debug info -D <value> Marks a conditional compilation flag as true -enable-library-evolution Build the module to allow binary-compatible library evolution -enforce-exclusivity=<enforcement> Enforce law of exclusivity -framework <value> Specifies a framework which should be linked against -Fsystem <value> Add directory to system framework search path -F <value> Add directory to framework search path -gdwarf-types Emit full DWARF type info. -gline-tables-only Emit minimal debug info for backtraces only -gnone Don't emit debug info -g Emit debug info. This is the preferred setting for debugging with LLDB. -help Display available options -index-store-path <path> Store indexing data to <path> -I <value> Add directory to the import search path -j <n> Number of commands to execute in parallel -L <value> Add directory to library link search path -l<value> Specifies a library which should be linked against -module-cache-path <value> Specifies the Clang module cache path -module-link-name <value> Library to link against when using this module -modul
(edited)
Avatar
omochimetaru 25-Apr-19 07:41 AM
@swift-5.1.5 -Xfrontend -emit-sil -Xfrontend -parse-as-library -O
func main() -> Int { let hoge: Int? = 1 let fuga = hoge .map { $0 * 2 } .map { $0 + 3 } .map { $0 * 4 } return fuga ?? 99 }
(edited)
Avatar
swift51 BOT 25-Apr-19 07:41 AM
sil_stage canonical import Builtin import Swift import SwiftShims func main() -> Int
(edited)
Avatar
norio_nomura 26-Apr-19 12:10 AM
プロトコル準拠って、デフォルトパラメータの有無も含むのか。 @swift-5.0.3
protocol X { func say(sentence: String) func say() } struct A: X { // error: Type 'A' does not conform to protocol 'X' func say(sentence: String = "I'm fine, you ?") { print("A : \(sentence)") } }
(edited)
Avatar
swift50 BOT 26-Apr-19 12:10 AM
exit status: 1 with stderr:
<stdin>:6:8: error: type 'A' does not conform to protocol 'X' struct A: X { ^ <stdin>:3:8: note: protocol requires function 'say()' with type '() -> ()'; do you want to add a stub? func say() ^
(edited)
Avatar
norio_nomura 26-Apr-19 12:10 AM
あいや、違うか。
00:12
デフォルトパラメータを使うと、コンクリートタイプの実装よりプロトコルエクステンションが優先されるらしい。 https://forums.swift.org/t/different-behavior-using-default-values-with-extension-and-struct/23675/1 (edited)
👋 Introduction Method defined on Extension seems to override the default method when default values are used. ⬇ Example import Foundation protocol X { func say(sentence: String) } extension X { func say(sentence: String = "Hello Jessy") { print("X :...
Avatar
norio_nomura 26-Apr-19 12:39 AM
プロトコル定義にはデフォルトパラメータの有無とか無いから、パラメータを渡さず呼び出した時にプロトコルが求めるメソッドと見なされないのか。
Avatar
ikesyo 26-Apr-19 12:43 AM
デフォルトパラメーターの話でいうと、プロトコル関係ないところで、引数なしのメソッドがあったところに、次のバージョンで引数ありの同名メソッド(デフォルトパラメーターあり)を追加・置き換えすると、一見ソース互換あるように思うけど、メソッド参照として使っていたところはソース互換なくなるし、シンボルとしても引数なし版が存在しなくなるのでバイナリ互換もなくなったりしますね (edited)
Avatar
norio_nomura 26-Apr-19 01:03 AM
なるほど。ABI維持を考えると、パラメータ無しオーバーロードとか必要になるのか。
Avatar
koher 26-Apr-19 02:28 AM
↓みたいなややこしさもあるし、デフォルトパラメータとオーバーロードの一元化をしてほしい気持ちになります。 @swift-5.0.3
func foo() -> Int { return 42 } func foo(_ x: Int = -1) -> Int { return x } print(foo())
Avatar
swift50 BOT 26-Apr-19 02:28 AM
42
Avatar
ikesyo 26-Apr-19 02:43 AM
デフォルトパラメーターはあくまでコールサイトでの展開なんですよねー
Avatar
koher 26-Apr-19 02:46 AM
せめてデフォルトパラメータとオーバーロードのコールサイトでの見た目が異なればいいんですけどねー。
02:46
デフォルト引数を明示化する構文とかだといいのかな。
02:47
↑の二つの foo に対して↓とか。
foo() foo(_)
02:48
Obj-C のライブラリでもよく明示的に nil を渡してたりしたし、明示的に省略するのは良さそうな気が。
Avatar
t.ae 13-May-19 12:47 AM
public enum RGB: CaseIterable { case r, g, b } public let count = 100_000_000 @inlinable public func testB() -> Int { var result = 0 for _ in 0..<count { for c in RGB.allCases { switch c { case .r: result += 1 default: break } } } return result }
このようなtestBを別モジュールから呼んだ場合RGB.allCasesで毎回Array生成しているらしくかなりコストが大きくなってしまう…… 自動実装のallCasesがinlinableじゃないってことなんでしょうけど盲点になりそう。
(edited)
00:48
RGB.allCasesをforの外で呼んだ場合のtestAとの比較
00:48
00:55
あれ?↑間違ってたかもしれないです。 同モジュール内でも遅いので単に最適化で展開されていないのか……
Avatar
t.ae 13-May-19 01:06 AM
調べてみたところ別のところに問題があるようで、
public enum RGB: Int, CaseIterable { case r, g, b } public let count = 100_000_000 public func testNormal() -> Int { var result = 0 for _ in 0..<count { for c in RGB.allCases { result += c.rawValue } } return result } @inlinable public func testInlinable() -> Int { var result = 0 for _ in 0..<count { for c in RGB.allCases { result += c.rawValue } } return result }
inlinableなはずのtestInlinableのほうがArray生成されてtestNormalより遅くなるという結果に。
Avatar
omochimetaru 13-May-19 01:10 AM
normalの方はallCasesがインライン化されてるの?
01:11
速度差だけからは、それは自明ではないと思うけど。
Avatar
t.ae 13-May-19 01:11 AM
time profilerで見るかぎりではtestInlinableのほうだけRGB.allCases.getterでallocateUninitializedBuffer云々出てます。
Avatar
omochimetaru 13-May-19 01:12 AM
なるほど
Avatar
t.ae 13-May-19 01:13 AM
これモジュールまたがなくて同一モジュール内でもinlinableついてるかどうかで変わってる気が……
Avatar
omochimetaru 13-May-19 01:13 AM
インライン化するかどうかは自明ではないからね
01:13
inlineableはインライン化可能であることを示すだけで
01:13
そもそもインライン化は速度低下することもあるから
Avatar
t.ae 13-May-19 01:13 AM
単一モジュール内でもinlinableって影響あるんですかね?
Avatar
omochimetaru 13-May-19 01:14 AM
同一モジュールの場合はついててもついてなくても
01:14
インライン化されたりされなかったりする という認識です
01:15
そのアトリビュートはコードを公開するって意味で、
01:15
同一モジュール内からコードはそもそも見えてるから変化無い
Avatar
t.ae 13-May-19 01:15 AM
ですよね
Avatar
omochimetaru 13-May-19 01:17 AM
自動生成されるallCasesにinlinableがついててもいいんじゃないかな
Avatar
t.ae 13-May-19 01:19 AM
常に一定のはずですしそうですよね。 bugsのほう経由で出してみます。
Avatar
omochimetaru 13-May-19 01:20 AM
常に一定というか、議論としては
01:20
enumのcase定義が
01:20
frozenかどうかと同じになると思う
01:20
frozenなenumならcaseが固定なのでオーケー
Avatar
t.ae 13-May-19 01:28 AM
むしろfrozenでない場合を考えて、常に大丈夫な現状の形になってるってこともあるかもですね。
Avatar
omochimetaru 13-May-19 01:30 AM
とりあえず保守的に作って、深く検討されてないというのはありそう
01:30
パフォーマンス上ボトルネックになる使い方がそうそう思いつかんし。
Avatar
omochimetaru 13-May-19 06:55 AM
On reflection, I have to say that I like this solution best. It is very similar in flavor to maybeNilObject?.someMethod() I might even argue that it should only be used for Void return types, just like that method call becomes essentially void if the object is nil. Kurt...
06:55
doIt { [guard weak self] in //... code }
06:55
↑この記法のアイデア初めて見たけどかなり良くない?
Avatar
tarunon 13-May-19 10:06 AM
おお!??めっちゃいい
10:07
んですが、返り値Voidのみ動きそう (edited)
Avatar
omochimetaru 13-May-19 10:08 AM
だいたいVoidだしVoidじゃないときは普通に書けばいいんじゃないか
Avatar
tarunon 13-May-19 10:08 AM
mapとかあるんすよ
Avatar
omochimetaru 13-May-19 10:08 AM
mapでselfがnilのとき、結果はどうすればいいの?
Avatar
tarunon 13-May-19 10:08 AM
二進も三進もいかないときに発生しがち
10:08
返り値Optionalです
10:08
最後に束ねて捨てる
Avatar
omochimetaru 13-May-19 10:09 AM
nilでいいってこと?
Avatar
tarunon 13-May-19 10:09 AM
それはそう
10:09
だからー返り値Optionalなら使えるみたいな
Avatar
omochimetaru 13-May-19 10:09 AM
それならこの記法でもサポートできるね
Avatar
tarunon 13-May-19 10:09 AM
特別扱いが結構入ってきて辛そうだなと思った
Avatar
omochimetaru 17-May-19 04:09 PM
The core team discussed staticallyCall and other variants that incorporated the word "static". The problem is that this can exist as protocol requirements and on classes, which are dynamically dispatched (through existentials and subclasses). We'd prefer to avoid the oppor...
16:10
プロポーザル通ったあとに不満言って「もう決まったことだよ」って流れよくあるけど、callFunctionのスレは不満多め
Avatar
omochimetaru 24-May-19 01:15 AM
The Core Team discussed this and has decided to further revise the proposal to name the operator function func callAsFunction(). We are comfortable with enabling this functionality purely based on nothing more than the name of a function, and we are not persuaded that init and subscript (which both have substantially different semantic and syntactic rules and are not simply functions) provide important precedents here requiring a new declaration introducer.
Thank you all for the discussion. John McCall Bikeshed Manager
01:15
callAsFunction に決まったみたい
Avatar
omochimetaru 24-May-19 01:25 AM
Bikeshed Managerちょっと皮肉っぽく聞こえるw
😅 1
Avatar
koher 30-May-19 05:50 AM
allSatisfy 加えるなら someSatisfy 的なのもほしくないですか? and と or 的に。 https://github.com/apple/swift-evolution/blob/master/proposals/0207-containsOnly.md
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
Avatar
omochimetaru 30-May-19 05:51 AM
containsでは対がわかりにくいってことですか?
Avatar
koher 30-May-19 05:51 AM
ああそうか。 contains か。
Avatar
omochimetaru 30-May-19 05:51 AM
はい。
05:51
そもそもSE0207はcontainsOnlyのプロポーザルでした
Avatar
koher 30-May-19 05:51 AM
Bool コレクションに対する andor ベースで考えてたから
Avatar
t.ae 30-May-19 05:52 AM
Alternatives consideredあたりに書かれてますね。
Avatar
omochimetaru 30-May-19 05:52 AM
containsとcontainsOnlyで対でわかりやすいぜって意見もあったけどallSatisfyになった。
Avatar
koher 30-May-19 05:52 AM
なるほど。
05:52
あとは、 Sequence where Element == Bool に対する API がほしいかも。
Avatar
t.ae 30-May-19 06:04 AM
// x.allFalse() x.allSatisfy(!) !x.contains(true)
たしかに現状使えるのだと前者のほうが短いのでこう書きたくなる(ならない)
Avatar
omochimetaru 30-May-19 06:04 AM
むむっ
06:05
array.allSatisfy(\.self)
06:05
これの出番か?
06:05
@swift-nightly
[true, true, true].allSatisfy(\.self)
Avatar
swiftNightly BOT 30-May-19 06:05 AM
exit status: 1 with stderr:
<stdin>:1:31: error: cannot convert value of type 'WritableKeyPath<_, _>' to expected argument type '(Bool) throws -> Bool' [true, true, true].allSatisfy(\.self) ^~~~~~
Avatar
omochimetaru 30-May-19 06:05 AM
未実装か
Avatar
t.ae 30-May-19 06:07 AM
x.allSatisfy(Bool.init(_:))
いまつかえるのだとこれですね。
06:08
グローバルに恒等関数があったら便利かもしれない
Avatar
omochimetaru 30-May-19 06:08 AM
\.selfがほぼidだよ
Avatar
t.ae 30-May-19 06:09 AM
そうですね。Swiftの場合はこの道が正しそう。 (edited)
Avatar
omochimetaru 30-May-19 06:09 AM
一応関数型への暗黙変換であってそれ自体はKeyPath型だから
06:10
KeyPathと関数の両方でオーバーロードされたりすると、ちゃんとしたidとは振る舞い変わっちゃうど。 (edited)
Avatar
t.ae 30-May-19 06:13 AM
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
Avatar
omochimetaru 30-May-19 06:13 AM
うん。
Avatar
koher 30-May-19 06:39 AM
x.allSatisfy(!) ww
06:40
and とか or が使いやすそう。
[true, true, false].and() [true, true, false].or()
Avatar
omochimetaru 30-May-19 06:41 AM
.all.any (edited)
Avatar
koher 30-May-19 06:42 AM
allSatisfy との対では all がわかりやすい
Avatar
lovee 30-May-19 08:32 AM
問題は今のSwiftのサジェスト機能がバグってて、extension Sequence where Element == Bool で実装したメソッドは全ての Sequence のサジェストに出てきちゃうんですよね…w (edited)
08:36
ワークアラウンドとして protocol LogicalOperatable 作って static func &&static func || 宣言して、extension Bool: LogicalOperatable 適合して extension Sequence where Element: LogicalOperatableand()or() もしくは all()any() 作れば問題ない
Avatar
omochimetaru 30-May-19 08:37 AM
["a"].だとjoinedの候補でるけど、[1].だと出てこないから、
08:37
extension Array where Self.Element == String はうまく動いてそう
08:38
あれ? joined ってSequenceに生えてるわけじゃないのか?
Avatar
koher 30-May-19 08:43 AM
サジェストで思い出しましたが、 Apple の Swift のドキュメントに出てくる
Available when Element conforms to Sequence.
とかって前から出てましたっけ?最近出てくるようになったような気がしてるんですが・・・。↓の joined() とか。 https://developer.apple.com/documentation/swift/array
Avatar
tarunon 30-May-19 09:18 AM
あれ?それSequenceでバグってましたか?Arrayにextension生やすと全部に生えるのは把握してましたが
09:18
Optionalだとバグるので対策にprotocol作った記憶がある
09:25
記憶が混濁してそう
Avatar
lovee 31-May-19 05:16 AM
あ、今試してみたらSequenceなら大丈夫でした、Arrayはだめですね
👍 1
05:16
05:16
Avatar
omochimetaru 31-May-19 05:17 AM
joinedはArray<String>に対して書かれているのでますます謎だ
Avatar
rintaro 31-May-19 05:22 AM
その辺のrequirement付きで適用できない候補がコード補完に出てきてしまう問題は次のバージョンで治ってるはずです。
Avatar
omochimetaru 31-May-19 05:23 AM
Avatar
rintaro 31-May-19 05:24 AM
We used to return decls from extension with non-matching same type requirements. e.g. struct S&lt;T&gt; { } extension S where T == String { func foo() {} } S&lt;Int&gt;().#HERE# /...
🎉 2
Avatar
lovee 31-May-19 05:28 AM
Avatar
norio_nomura 04-Jun-19 01:45 AM
Function Builder、draftに書かれたHTMLBuilderをXcode 11 betaで動かそうとしてるけど、いまいちうまくいかないな。 https://forums.swift.org/t/pitch-function-builders/25167
It's always been a goal of Swift to support declarative programming, and the language can be quite good for it, but some kinds of "declaration" fit better into the current language than others. In particular, heterogeneous trees with a lot of hard-coded structure — such as...
Avatar
omochimetaru 04-Jun-19 05:01 AM
関数の型に対してアノテーションつけといて、記法がすり替わるのか
05:03
あ、型じゃなくてラベルについてるのか
Avatar
norio_nomura 04-Jun-19 05:46 AM
今の実装はvariadic parameterなbuildBlockをサポートしてるのかな?
Avatar
omochimetaru 04-Jun-19 05:47 AM
ViewBuilderのリファレンス見ると引数10個?までオーバーロードされてるから、variadicじゃ無さそうに見えます
05:49
That’s needed only because (1) SwiftUI wants to propagate sub-view types into the return type to enable some optimizations and (2) Swift doesn’t have variadic generics yet. It’s not a long-term problem, and most other libraries can just use variadic arguments.
Avatar
norio_nomura 04-Jun-19 06:11 AM
ぬぬ。あとdraftで使われてるbuildExpressionとかも無さげ。
06:14
@_functionBuilderViewBuilderに最低限必要な機能だけ実装されてるぽい。
Avatar
omochimetaru 04-Jun-19 06:15 AM
なるほど
Avatar
norio_nomura 05-Jun-19 01:17 AM
動作するサンプルが載ってた。 https://github.com/apple/swift-evolution/pull/1047
This is an example of how to use the function builder feature to make a DSL for HTML in Swift. It builds off of the example in the function builders proposal here: #1046 This should not be merged, ...
Avatar
kateinoigakukun 05-Jun-19 09:14 AM
このサンプルコードはコンパイル通らない https://developer.apple.com/documentation/swiftui/staticmember
09:16
これ見た限りだとStaticMember<Base>のBaseがcolorStyleのシグネチャに使われてないのに推論されてて、型推論が強化されたのかと思ったけど、実際は func colorStyle<S : ColorStyle>(_ style: S.Member) -> Self.Modified<ColorStyleModifier<S>> みたいな感じでラップされて伝播してた (edited)
09:18
このテクは今までも使えたけど型パラがどんどん膨れ上がっていくので辛いことになってたけど、ORTのおかげで使いやすくなった。
Avatar
omochimetaru 05-Jun-19 09:19 AM
これどうなってんだ?
Avatar
tarunon 05-Jun-19 09:20 AM
ORTあるとかなり型消去考えずに済むの良いですね
Avatar
omochimetaru 05-Jun-19 09:20 AM
RedStyleは struct RedStyle : ColorStyle
Avatar
kateinoigakukun 05-Jun-19 09:20 AM
そうです
Avatar
omochimetaru 05-Jun-19 09:21 AM
てことは、 RedStyle.Member.blue とかも生えてる?
Avatar
kateinoigakukun 05-Jun-19 09:21 AM
いや、それが生えてる必要はないはずです
Avatar
omochimetaru 05-Jun-19 09:22 AM
必要は無いけど、 extension StaticMember where Base : ColorStyle これのせいで生えてそう
09:23
で、そうすると、
MyView().colorStyle(.red)
↑これはなんで解決できるんだ? func colorStyleSは何が推論されてるの?
Avatar
kateinoigakukun 05-Jun-19 09:23 AM
SwiftUIの型見た感じだとStaticMemberのconstionalなメンバとして生えてるだけですね
09:24
あれ、たしかに。
Avatar
omochimetaru 05-Jun-19 09:24 AM
型パラがどんどん膨れ上がっていく
このパターンのジェネリクスに名前がほしいのでとりあえず「雪だるまジェネリクス」と呼んでみたい
Avatar
kateinoigakukun 05-Jun-19 09:24 AM
あ、いや
Avatar
tarunon 05-Jun-19 09:24 AM
マトリョシカって呼んでたw
Avatar
omochimetaru 05-Jun-19 09:25 AM
constional
この言葉はじめてみた
Avatar
kateinoigakukun 05-Jun-19 09:26 AM
redの型がStaticMember<RedColor>だからBaseが推論できてるはず
09:26
タイポ…
Avatar
omochimetaru 05-Jun-19 09:27 AM
conditionalか
Avatar
kateinoigakukun 05-Jun-19 09:27 AM
ですです
Avatar
omochimetaru 05-Jun-19 09:27 AM
んん〜?
Avatar
kateinoigakukun 05-Jun-19 09:28 AM
StaticMember.redはStaticMember<Red>になるじゃないですか?
Avatar
omochimetaru 05-Jun-19 09:29 AM
StaticMember.red はおかしくない?
09:29
StaticMember<Base>.redBase を何かで埋めないと。
09:30
あ、見てる場所が違うのか。 俺が気にしてるのは .colorStyle(.red) の推論ね。
09:30
{ return .init(.init()) } の方じゃない。
09:31
@swift-5.1.5
struct StaticMember<Base> { init(_ base: Base) {} } protocol ColorStyle { typealias Member = StaticMember<Self> } struct RedStyle : ColorStyle {} struct BlueStyle : ColorStyle {} extension StaticMember where Base : ColorStyle { static var red: RedStyle.Member { return .init(.init()) } static var blue: BlueStyle.Member { return .init(.init()) } } protocol View {} extension View { func colorStyle<S : ColorStyle>(_ style: S.Member) { } } struct MyView : View {} MyView().colorStyle(.red) MyView().colorStyle(.blue)
Avatar
swift51 BOT 05-Jun-19 09:31 AM
no output
Avatar
omochimetaru 05-Jun-19 09:34 AM
<S> StaticMember<S>.red って許されてるのか
Avatar
tarunon 05-Jun-19 09:35 AM
Baseが埋まってるからいけるんじゃないかなと思った
Avatar
omochimetaru 05-Jun-19 09:36 AM
@swift-5.1.5
struct StaticMember<Base> { init(_ base: Base) {} } protocol ColorStyle { typealias Member = StaticMember<Self> } struct RedStyle : ColorStyle {} struct BlueStyle : ColorStyle {} extension StaticMember where Base : ColorStyle { static var red: RedStyle.Member { return .init(.init()) } static var blue: BlueStyle.Member { return .init(.init()) } } protocol View {} extension View { func colorStyle<S : ColorStyle>(_ style: S.Member) { } } struct MyView : View {} MyView().colorStyle(RedStyle.Member.red) MyView().colorStyle(BlueStyle.Member.red)
(edited)
Avatar
swift51 BOT 05-Jun-19 09:37 AM
no output
Avatar
kateinoigakukun 05-Jun-19 09:37 AM
@swift-5.1.5 @swift-4.1.3
struct Static<Base> {} extension Static { static var foo: Static<Int> { return .init() } } func useMember<T>(member: Static<T>) {} useMember(member: .foo)
(edited)
Avatar
swift51 BOT 05-Jun-19 09:37 AM
no output (edited)
Avatar
omochimetaru 05-Jun-19 09:37 AM
MyView().colorStyle(RedStyle.Member.red) MyView().colorStyle(BlueStyle.Member.red)
↑これのどっちも通るわけですよ
09:37
RedStyle.MemberStaticMember<RedStyle>BlueStyle.MemberStaticMember<BlueStyle> だから
09:37
Baseがなんなのか確定しない
Avatar
swift41 BOT 05-Jun-19 09:38 AM
no output
Avatar
omochimetaru 05-Jun-19 09:40 AM
だから、Baseは不確定だけど Base = <S> S where S : ColorStyle な状態を解決としてるように思える (edited)
09:40
MyView().colorStyle(RedStyle.Member.red) MyView().colorStyle(BlueStyle.Member.red) MyView().colorStyle(.red) // これは↑のどちらでもない
Avatar
kateinoigakukun 05-Jun-19 09:41 AM
まあambiguousになるパターンはありますね
Avatar
omochimetaru 05-Jun-19 09:42 AM
ドット記法はただの推論じゃなくて、「書き下せないパターン」に落ちてる場合があるって事じゃないか
09:43
むむ
09:43
@swift-5.1.5
struct StaticMember<Base> { init(_ base: Base) {} } protocol ColorStyle { typealias Member = StaticMember<Self> } struct RedStyle : ColorStyle {} struct BlueStyle : ColorStyle {} extension StaticMember where Base : ColorStyle { static var red: RedStyle.Member { print(self) return .init(.init()) } } protocol View {} extension View { func colorStyle<S : ColorStyle>(_ style: S.Member) {} } struct MyView : View {} MyView().colorStyle(.red) MyView().colorStyle(RedStyle.Member.red) MyView().colorStyle(BlueStyle.Member.red)
Avatar
swift51 BOT 05-Jun-19 09:43 AM
StaticMember<RedStyle> StaticMember<RedStyle> StaticMember<BlueStyle>
Avatar
omochimetaru 05-Jun-19 09:44 AM
.redStaticMember<RedStyle>.red らしい。
Avatar
kateinoigakukun 05-Jun-19 09:45 AM
あー、わかった
Avatar
omochimetaru 05-Jun-19 09:45 AM
あ〜、.staticProp は その返り値の型と受ける型が同一って制約があるのか?
Avatar
kateinoigakukun 05-Jun-19 09:45 AM
ですね
Avatar
omochimetaru 05-Jun-19 09:47 AM
.redに対してStaticMember<S: ColorStyle> の状態で static var red をconditionalに見つけて、redの返り値が StaticMember<RedStyle> だから、.redStaticMember<RedStyle>.red の扱いになるのか
09:49
@swift-5.1.5
struct StaticMember<Base> { init(_ base: Base) {} } protocol ColorStyle { typealias Member = StaticMember<Self> } struct RedStyle : ColorStyle {} struct BlueStyle : ColorStyle {} extension StaticMember where Base : ColorStyle { static var red: RedStyle.Member { print(self) return .init(.init()) } } protocol View {} extension View { func colorStyle<S : ColorStyle>(_ style: S.Member) {} func anyStyle<S>(_ style: StaticMember<S>) {} } struct MyView : View {} MyView().colorStyle(.red) MyView().anyStyle(.red)
Avatar
swift51 BOT 05-Jun-19 09:49 AM
StaticMember<RedStyle> StaticMember<RedStyle>
Avatar
omochimetaru 05-Jun-19 09:49 AM
conditionalでない時点で発見して試みるのか。
09:50
@swift-5.1.5
struct StaticMember<Base> { init(_ base: Base) {} } protocol ColorStyle { typealias Member = StaticMember<Self> } protocol FontStyle { typealias Member = StaticMember<Self> } struct RedStyle : ColorStyle {} struct BlueStyle : ColorStyle {} struct RedFontStyle : FontStyle {} extension StaticMember where Base : ColorStyle { static var red: RedStyle.Member { print(self) return .init(.init()) } } extension StaticMember where Base : FontStyle { static var red: RedFontStyle.Member { print(self) return .init(.init()) } } protocol View {} extension View { func colorStyle<S : ColorStyle>(_ style: S.Member) {} func fontStyle<S: FontStyle>(_ style: S.Member) {} func anyStyle<S>(_ style: StaticMember<S>) {} } struct MyView : View {} MyView().colorStyle(.red) MyView().fontStyle(.red) MyView().anyStyle(.red)
Avatar
swift51 BOT 05-Jun-19 09:50 AM
exit status: 1 with stderr:
<stdin>:41:20: error: ambiguous use of 'red' MyView().anyStyle(.red) ^ <stdin>:16:16: note: found this candidate static var red: RedStyle.Member { ^ <stdin>:23:16: note: found this candidate static var red: RedFontStyle.Member { ^
Avatar
omochimetaru 05-Jun-19 09:51 AM
同じものをもう一組用意すると、曖昧な場合はちゃんとエラーだ
09:58
あ、このStaticMemberって
09:58
これをやるためのヘルパージェネリクスなのかw
09:59
え、じゃあこれ自体に StaticMember<S> で引数を受けてる意味はなくて
09:59
中ではすぐに style.base<S> を取り出すだけ?
Avatar
kateinoigakukun 05-Jun-19 10:01 AM
そのはず
Avatar
omochimetaru 05-Jun-19 10:01 AM
func background<Background>(Background, alignment: Alignment) -> Self.Modified<_BackgroundModifier<Background>> func background<S>(S.Member) -> Self.Modified<_BackgroundModifier<Rectangle.Filled<S>>> func background<S>(S.Member, cornerRadius: Length) -> Self.Modified<_BackgroundModifier<RoundedRectangle.Filled<S>>> func background<S>(S, cornerRadius: Length) -> Self.Modified<_BackgroundModifier<RoundedRectangle.Filled<S>>>
10:01
そういうことか
10:02
func background<S>(_ content: S.Member, cornerRadius: Length) -> Self.Modified<_BackgroundModifier<RoundedRectangle.Filled<S>>> where S : ShapeStyle func background<S>(_ content: S, cornerRadius: Length) -> Self.Modified<_BackgroundModifier<RoundedRectangle.Filled<S>>> where S : ShapeStyle
(edited)
10:04
↑この2つは ただドット記法させるためだけのオーバーロードと、本質的なインターフェースだ
10:06
これはSwiftならではのデザインパターンだなあ
Avatar
kateinoigakukun 05-Jun-19 10:10 AM
どっちも用意してあるのか
Avatar
omochimetaru 05-Jun-19 10:11 AM
そうじゃないと、普通に ShapeStyle の値をもってるときに
10:11
無意味に StaticMember(style) って書かないといけなくなる
Avatar
kateinoigakukun 05-Jun-19 10:14 AM
ambiguousになるパターンもこれがないと詰みそう
10:14
いや、大丈夫か
Avatar
omochimetaru 05-Jun-19 10:19 AM
StaticMember<StaticMember<ColorStyle>> とかやると曖昧になるかもしれんけど
10:19
目的外利用だね
Avatar
omochimetaru 21-Jun-19 09:09 AM
protocol CopyInitializable {} extension CopyInitializable { init(copy: Self) { self = copy } } class Animal : CopyInitializable { init() {} convenience init(a: Int) { let copy = Animal() // `Self`にforce castしたいがここに`Self`が書けないので // self.init(copy: copy as! Self) // type(of: self)でSelf型を作って、 // それをジェネリクスに渡すことで`as!`を実行できる self.init(copy: forceCast(copy, to: type(of: self))) } } func forceCast<X, T>(_ x: X, to type: T.Type) -> T { return x as! T }
09:09
↑トリッキー
Avatar
norio_nomura 25-Jun-19 10:39 AM
🤔 @swift-5.0.3
import Foundation let gregorian = Calendar(identifier: .gregorian) let utc = TimeZone(identifier: "UTC")! let components = gregorian.dateComponents(in: utc, from: Date()) func date(from components: DateComponents, with nanosecond: Int) -> Date { var components = components components.nanosecond = nanosecond return components.date! } print(date(from: components, with: 999499976).description) print(date(from: components, with: 999499977).description)
Avatar
swift50 BOT 25-Jun-19 10:39 AM
2019-06-25 10:39:38 +0000 2019-06-25 10:39:39 +0000
Avatar
omochimetaru 25-Jun-19 10:47 AM
精度限界関係かしら
Avatar
norio_nomura 25-Jun-19 11:26 AM
なるほど。 @swift-5.0.3
import Foundation let iso8601WithFractionalSecondFormatter: DateFormatter = { let formatter = DateFormatter() formatter.locale = Locale(identifier: "en_US_POSIX") formatter.dateFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.SSSSSS" formatter.timeZone = TimeZone(secondsFromGMT: 0) return formatter }() let gregorian = Calendar(identifier: .gregorian) let utc = TimeZone(identifier: "UTC")! let components = gregorian.dateComponents(in: utc, from: Date()) func date(from components: DateComponents, with nanosecond: Int) -> Date { var components = components components.nanosecond = nanosecond return components.date! } let date1 = date(from: components, with: 999499976) print(iso8601WithFractionalSecondFormatter.string(from: date1)) print(gregorian.dateComponents(in: utc, from: date1).nanosecond!) let date2 = date(from: components, with: 999499977) print(iso8601WithFractionalSecondFormatter.string(from: date2)) print(gregorian.dateComponents(in: utc, from: date2).nanosecond!)
Avatar
swift50 BOT 25-Jun-19 11:26 AM
2019-06-25T11:26:43.999000 999499917 2019-06-25T11:26:44.000000 999500036
Avatar
omochimetaru 25-Jun-19 11:28 AM
Macでは結果が違ったりするのかな
Avatar
norio_nomura 25-Jun-19 11:30 AM
同じです。
Avatar
omochimetaru 25-Jun-19 12:16 PM
ほ~
Avatar
norio_nomura 25-Jun-19 12:18 PM
YamsのYAMLEncoderで、10000回に5回くらいしか起きないバグの原因になってる。 (edited)
Avatar
norio_nomura 26-Jun-19 07:26 AM
昨日のDateFormatter、ドキュメントによるとdateFormat文字列には Unicode Technical Standard #35 を使うと書かれてるけど、S Fractional Secondの扱いが Unicode Technical Standard #35 と違ってるんだ。 https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/DataFormatting/Articles/dfDateFormatting10_4.html#//apple_ref/doc/uid/TP40002369-SW13 (edited)
Explains how to use Cocoa formatters to create and validate text in text fields and other cells.
07:27
Unicode Technical Standard #35 によると
Fractional Second - truncates (like other time fields) to the count of letters.
となってるけど、実際の挙動はtruncateではなくroundになってる。 http://www.unicode.org/reports/tr35/tr35-31/tr35-dates.html#Date_Format_Patterns
(edited)
Avatar
omochimetaru 26-Jun-19 07:32 AM
The Foundation Project, providing core utilities, internationalization, and OS independence - apple/swift-corelibs-foundation
07:33
public struct Date : ReferenceConvertible, Comparable, Equatable { fileprivate var _time: TimeInterval }
07:35
Doubleの精度はおよそ15桁だから、 1970から50年で 1,576,800,000秒で10桁使うから
07:36
ミリ秒3桁までは13桁でいけそうだけど
07:36
マイクロ秒6桁になるとギリギリアウトぐらいか
Avatar
norio_nomura 26-Jun-19 07:38 AM
なるほど。確かに手元の検証は6~7桁でおかしくなる。
Avatar
omochimetaru 26-Jun-19 07:39 AM
原点が1970年か2000年かちょっとわからんけど、原点周辺なら精度が出そう。
Avatar
norio_nomura 26-Jun-19 07:40 AM
あ、TimeIntervalReferenceDateは2001年1月1日0:00だ。 @swift-5.0.3
import Foundation print(Date(timeIntervalSinceReferenceDate: 0)) print(Date().timeIntervalSinceReferenceDate)
(edited)
Avatar
swift50 BOT 26-Jun-19 07:41 AM
2001-01-01 00:00:00 +0000 583227738.026557
(edited)
Avatar
omochimetaru 26-Jun-19 07:47 AM
@swift-5.1.5
import Foundation let iso8601WithFractionalSecondFormatter: DateFormatter = { let formatter = DateFormatter() formatter.locale = Locale(identifier: "en_US_POSIX") formatter.dateFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.SSSSSS" formatter.timeZone = TimeZone(secondsFromGMT: 0) return formatter }() var d = Date(timeIntervalSinceReferenceDate: 0) for _ in 0..<10 { print(iso8601WithFractionalSecondFormatter.string(from: d)) d += 0.0001 }
Avatar
swift51 BOT 26-Jun-19 07:47 AM
2001-01-01T00:00:00.000000 2001-01-01T00:00:00.000000 2001-01-01T00:00:00.000000 2001-01-01T00:00:00.000000 2001-01-01T00:00:00.000000 2001-01-01T00:00:00.001000 2001-01-01T00:00:00.001000 2001-01-01T00:00:00.001000 2001-01-01T00:00:00.001000 2001-01-01T00:00:00.001000
Avatar
norio_nomura 26-Jun-19 07:50 AM
そう、今は3桁で四捨五入した結果しか返してくれない。
Avatar
omochimetaru 26-Jun-19 07:50 AM
Formatterのほうはそうなんですね。
07:50
@swift-5.1.5
import Foundation let iso8601WithFractionalSecondFormatter: DateFormatter = { let formatter = DateFormatter() formatter.locale = Locale(identifier: "en_US_POSIX") formatter.dateFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.SSSSSS" formatter.timeZone = TimeZone(secondsFromGMT: 0) return formatter }() let gregorian = Calendar(identifier: .gregorian) let utc = TimeZone(identifier: "UTC")! let components = gregorian.dateComponents(in: utc, from: Date()) var d = Date(timeIntervalSinceReferenceDate: 0) // 2001年 for _ in 0..<10 { print(gregorian.dateComponents(in: utc, from: d).nanosecond!) d += 0.000001 } d = Date(timeIntervalSinceReferenceDate: 86400 * 365 * 20) // 2021年 for _ in 0..<10 { print(gregorian.dateComponents(in: utc, from: d).nanosecond!) d += 0.000001 }
Avatar
swift51 BOT 26-Jun-19 07:50 AM
0 1000 2000 3000 4000 5000 5999 6999 8000 9000 0 953 1907 2861 3814 4768 5722 6675 7629 8583
Avatar
omochimetaru 26-Jun-19 07:50 AM
↑原点から遠ざかるほどガバガバになる
😞 1
Avatar
norio_nomura 26-Jun-19 07:53 AM
JSONEncoderは標準機能だと、任意のDateのインスタンスを元の値を維持したままDateFormatter使ってエンコード/デコード出来ないから、Date()のround tripテストだけ特別なことしてる。 https://github.com/apple/swift/blob/master/test/stdlib/TestJSONEncoder.swift#L255-L257 (edited)
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
Avatar
omochimetaru 26-Jun-19 07:54 AM
ひえ〜
07:54
この辺信用ならんから、API設計ではJSON文字列で扱うようにして、パーサも自作してる。
Avatar
norio_nomura 26-Jun-19 07:55 AM
あ、DateFormatter使ったエンコード/デコードだ。
07:56
標準は Doubleにするから大丈夫だったはず。 (edited)
07:56
あいや、これDoubleだ。
07:58
あ、JSONSerializationDoubleの精度を落としちゃうからダメって書かれてる…
08:00
🤔 あれ?公式のリポジトリ内では、JSONEncoderは任意のDateインスタンスのエンコード/デコードを標準の手法でテストされてない?
08:04
ISO8601DateFormatterも精度が足りないし。
Avatar
norio_nomura 30-Jun-19 05:08 AM
DateFormatterがsub-millisecondで四捨五入する挙動はドキュメントと一致していない、というissueを登録した。 https://bugs.swift.org/browse/SR-11049
Avatar
omochimetaru 01-Jul-19 01:21 AM
えらい
Avatar
omochimetaru 04-Jul-19 12:50 AM
Hey all, As per the GSoC announcement, @jansvoboda11 is working on Integration of libSyntax with the compiler pipeline with @rintaro as his mentor. I'd like to provide more details on what the project entails and what changes you should expect to see coming to the Swift repo...
00:50
りんたろープロジェクトの詳細なアナウンスが出た
00:52
パーサーの処理をlibSyntaxに一本化して、libSyntax->旧libASTに変換する、パイプラインに書き換えると。
😀 1
00:59
そこまではできそうだけど、その後のステージでASTの型掴んでるところを段階的移行するのが難しそうなんだよなあ
02:02
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
02:02
レビューの決着ちゃんとアナウンスされてないけど、とりあえずフォーマッターの実装がappleのリポジトリに爆誕した
02:03
25000行のコミットウケる
Avatar
kitasuke 11-Jul-19 02:24 AM
ついに! Descriptionもないw
Avatar
norio_nomura 11-Jul-19 04:36 AM
https://github.com/apple/swift-format/pull/1 試したけど、Xcode 11 beta 1固定になってる。
Avatar
omochimetaru 11-Jul-19 04:37 AM
固定って何のことですか?
Avatar
norio_nomura 11-Jul-19 04:38 AM
Package.swiftdependencies.package(url: "https://github.com/apple/swift-syntax", .revision("swift-DEVELOPMENT-SNAPSHOT-2019-07-10-m")), に書き換えてswift-5.1-DEVELOPMENT-SNAPSHOT-2019-07-09-aを使うと動いた。 (edited)
Avatar
omochimetaru 11-Jul-19 04:39 AM
.package(url: "https://github.com/apple/swift-syntax", .revision("xcode11-beta1")),
04:39
これか
04:40
そっか、SwiftPMで実行ターゲットとしてビルドできるんですね
Avatar
norio_nomura 11-Jul-19 04:41 AM
TOOLCHAIN (SwiftSyntax)のバージョンを合わせないと、
Unable to format ../../SwiftLint/Package.swift: SwiftSyntax parser library isn't compatible
とか言われて動かない。
Avatar
omochimetaru 11-Jul-19 04:42 AM
SwiftSyntaxのバージョン合わせややこしいですね
04:42
SwiftSyntax自体がコンパイラバイナリに依存してるからしょうがないのか
04:43
でもSwiftPMの思想的にはそれは良くない状態に感じる
Avatar
norio_nomura 11-Jul-19 04:46 AM
ここでlibSyntaxが使う型情報のハッシュを計算しておいて、実行時にこれを照合して互換性があるライブラリかチェックしてるぽい。 https://github.com/apple/swift/blob/master/utils/gyb_syntax_support/__init__.py#L164-L170 (edited)
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
Avatar
omochimetaru 11-Jul-19 04:47 AM
バージョン番号とかじゃなくて定義そのものなのか。
Avatar
norio_nomura 11-Jul-19 04:48 AM
gybに食わせるPythonで記述された型情報ぽい。
04:51
SwiftSyntaxに依存すると、TOOLCHAINにバンドルしないとほぼ成り立たないツールになってしまう様に見える。 (edited)
Avatar
omochimetaru 11-Jul-19 05:20 AM
SwiftSyntaxがそうだから、連鎖的にそうなっちゃいますよねえ
Avatar
omochimetaru 23-Jul-19 04:14 AM
The review of SE-0262: Demangle Function begins now and runs through July 29, 2019. The proposal is written by @Alejandro. Reviews are an important part of the Swift evolution process. All review feedback should be either on this forum thread or, if you would like to keep y...
04:14
demangle関数のstdlib入りレビュー (edited)
04:18
人間読む用の文字列にデマングルするだけじゃなくて、定義のツリー構造が取り出せる的な指摘がされてるな、そのとおりだ
Avatar
omochimetaru 29-Jul-19 02:02 AM
Swiftでテンプレートを含むC++のinteropだ!! https://t.co/zA5dhfRw2H
Avatar
koher 29-Jul-19 03:42 PM
@swift-5.0.3
struct Foo { var value: Int func a() -> Int { return value } mutating func b() -> Int { value += 1; return value } } print(type(of: Foo.a))
Avatar
swift50 BOT 29-Jul-19 03:42 PM
(Foo) -> () -> Int
Avatar
koher 29-Jul-19 03:42 PM
@swift-5.0.3
struct Foo { var value: Int func a() -> Int { return value } mutating func b() -> Int { value += 1; return value } } print(type(of: Foo.b))
Avatar
swift50 BOT 29-Jul-19 03:42 PM
exit status: 1 with stderr:
<stdin>:7:20: error: partial application of 'mutating' method is not allowed print(type(of: Foo.b)) ^
Avatar
koher 29-Jul-19 03:43 PM
↑これって (inout Foo) -> () -> Int じゃダメですか?
15:45
ダメか
Avatar
koher 29-Jul-19 04:21 PM
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
16:23
3 年前に Accept されたまま実装されてないのか。 https://bugs.swift.org/browse/SR-1051
Avatar
omochimetaru 30-Jul-19 01:20 AM
そういえばこれのAccept見たな
01:21
selfについてカリー化しないで第ゼロ引数に押し込めば、mutatingのinoutも問題ないのか。
01:21
まあ、メソッド呼び出しのときがそうだからそれはそうか。
Avatar
koher 30-Jul-19 08:11 AM
Accept されたのに長期間放置もあるんだね。
Avatar
omochimetaru 30-Jul-19 08:13 AM
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
08:13
↑これも、最近入ったけどAcceptはずっと前だったと思う
Avatar
koher 30-Jul-19 08:14 AM
昔は実装なしで提案できたからってのもあるのかな。
Avatar
omochimetaru 30-Jul-19 08:14 AM
昔はというか今もそれはそうだと思ってました
Avatar
norio_nomura 30-Jul-19 08:18 AM
正式な提案には実装が必要になったのでは。
Avatar
omochimetaru 30-Jul-19 08:25 AM
Develop the proposal: expand the rough sketch into a complete proposal, using the proposal template, and continue to refine the proposal on the forums. Prototyping an implementation and its uses along with the proposal is required because it helps ensure both technical feasibility of the proposal as well as validating that the proposal solves the problems it is meant to solve.
08:26
ほんとだ。Prototyping is required だ。
08:28
2017-09に is encouraged から is *required* に変わってたのか。
Avatar
koher 01-Aug-19 08:39 AM
class existential container https://github.com/apple/swift/blob/master/docs/ABI/TypeLayout.rst#class-existential-containers が witness table へのポインタを保持しないといけない理由って何でしょう?クラスの場合、オブジェクトが vtable を参照しているのでそちらから必要なメソッドを引けないですか?複数プロトコルに適合しているときの扱いをシンプルにするため?
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
Avatar
omochimetaru 01-Aug-19 09:54 AM
引けるか引けないかでいうと引けるはずですね 実行時のconditional conformanceがあるぐらいなので
09:55
事前に紐付けられたテーブルと実行時に探索した結果が異なる場合がありえるかどうかは思いつかないですが
09:55
少なくともパフォーマンス上かなりロスがありそう
09:57
ただ昔のSwiftはランタイムリフレクションが今ほど無かったんで昔は引けなかった気も?
10:00
あ、あとメソッドを引くというかテーブルを引くだと思います
Avatar
norio_nomura 02-Aug-19 01:41 AM
クラスのメタデータには、そのクラスのプロトコルwitness tableって含まれていないのでは。
Avatar
omochimetaru 02-Aug-19 01:47 AM
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
01:48
↑このランタイム関数で、(クラスに限らず)メタタイプとProtocolからWitnessTableを引っ張れます
01:49
実装詳細は追ってないけど、メタデータとしてそれが入ってないとできないと思う。
Avatar
norio_nomura 02-Aug-19 01:52 AM
生成されたアセンブラを読むと、メタデータ内の情報は使わず、そのクラスのwitness tableを返すシンボルが存在する前提でそれを呼び出すコードが生成されているのですよね。 (edited)
Avatar
norio_nomura 02-Aug-19 02:06 AM
swiftc -emit-assembly ClassExistencial.swift|swift demangle>ClassExistencial.asm - ClassExistencial.asm
02:13
上記gistで、class C1のメタデータはこの辺り。witness tableに関する情報は含まれてないように見える。 https://gist.github.com/norio-nomura/5cf4615b4334eeb7d4b5081aeb7e1536#file-classexistencial-asm-L579-L600
02:16
witness tableを取り出すところはここ。直接シンボルを参照してる。 https://gist.github.com/norio-nomura/5cf4615b4334eeb7d4b5081aeb7e1536#file-classexistencial-asm-L25 (edited)
Avatar
omochimetaru 02-Aug-19 02:18 AM
静的にわかるケースだとそうなると思います ランタイム関数のconformsToProtocolが使われるケースがわかったら共有します
Avatar
norio_nomura 02-Aug-19 02:21 AM
そうか、動的チェックのコードを見ないといけないのか。
Avatar
koher 02-Aug-19 02:25 AM
実装上こうなってるからできないという理由とは独立して、なぜそのような設計にしたのかという話があると思います。 Java 等ではインタフェース型変数はアドレスを格納するだけで vtable からメソッドの実体を引くので、変数は( 64 ビット環境なら) 8 バイトで済みますよね? Swift の Class Existential Container だと Witness Table へのポインタを含むために↓では 16 バイトになってしまうわけですが、そのような設計にした理由は何だと考えられますか? @swift-5.0.3
protocol Animal: AnyObject { func foo() -> Int } class Cat: Animal { func foo() -> Int { return 42 } } let cat = Cat() let animal: Animal = cat print(MemoryLayout.size(ofValue: cat)) print(MemoryLayout.size(ofValue: animal))
Avatar
swift50 BOT 02-Aug-19 02:25 AM
8 16
Avatar
norio_nomura 02-Aug-19 02:26 AM
vtableだけではプロトコルメソッドを探せないからでは。
Avatar
koher 02-Aug-19 02:27 AM
それは実装上の都合ではないですか?
Avatar
omochimetaru 02-Aug-19 02:27 AM
Java 等ではインタフェース型変数はアドレスを格納するだけで vtable からメソッドの実体を引くので
ここはちょっと実際と違うと思います
Avatar
norio_nomura 02-Aug-19 02:28 AM
classメタデータをObjective-Cと互換にするという制約で実現できないのでは。
Avatar
koher 02-Aug-19 02:29 AM
@omochimetaru Java 等のインタフェース型変数は 8 バイトでアドレスを格納してるわけではないということ?
Avatar
omochimetaru 02-Aug-19 02:32 AM
インターフェースが要求するメソッドを並べたインターフェーステーブルがあって、
02:32
クラスのインターフェースの充足は事前に静的にわかるので
02:32
そのテーブルは生成されていて
02:33
インターフェースにアップキャストしたオブジェクトっていうのはそれで扱われてるはずです
02:33
この辺の詳細はJVMバイトコードとは独立してJVMランタイム固有の部分みたいだけど
02:33
以前IBMのスライドで見た。
02:33
C++のインターフェースアップキャストも同じような構造でコンパイルされます。
02:33
そうしないと、対応するメソッドの検索がO(1)にできないからです
02:34
こうしておくとインターフェースとメソッド番号(index)でテーブルから一発で引ける。
02:34
で、それが8バイトポインタから間接で引いてるのか、 インターフェースキャストしたthisとインターフェーステーブルのペアの16バイトなのか、 そもそもペアで扱うのかとかは知らない。
02:35
そのような設計にした理由
これに関しては、こうしておいたほうが「witnessテーブルを引く」実行コストが少ないからだと思います。
02:36
ある型Tがany Pコンテナに格納される部分のコードでは、witness table of T for P はコンパイル時に静的に引けるので
02:36
any Pコンテナへのアップキャストのところで静的にテーブルを格納できて、 any P をopenする側ではもうそこにテーブルがあるので取り出せば呼び出せる。
Avatar
koher 02-Aug-19 02:36 AM
具象クラスの継承と違うのは、 interface/protocol は多重に implement/conform できるから?
Avatar
omochimetaru 02-Aug-19 02:37 AM
そうですね。 親が一個だけの継承に関しては、親子のつながりでvtableを上から埋めていけば、
02:37
アップキャスト用のテーブルを用意しなくても、子のテーブル is 親のテーブルのABI互換性が得られます。
02:38
C++の場合そのへん賢くて、 親が1系統である限りテーブルのオフセットは発生しないけど、 親が2ついたりすると、片方の親へのアップキャスト(static_cast)は、thisのアドレスがズレたりしますよ。 (edited)
02:40
Rustのtrait implも、同じような感じでthisとimpl tableのペアだよって公式文書に書いてあったと思う。
Avatar
koher 02-Aug-19 02:43 AM
うーん、 Java ではインタフェース型だとしても変数側でペアで持ってないと思うんだけど(これに関しては別途確認するとして)、それが正しいとすると Swift と Java は別の方式を選択してるわけで、何の違いが別の選択をさせてるんだろう?
Avatar
omochimetaru 02-Aug-19 02:44 AM
変数側でペアで持ってない
インターフェース型の変数のサイズはペアの可能性はありますね
02:45
何の違いが別の選択をさせてる
少なくとも、Javaではポリモーフィズムを考えるところでは全部参照型だけ考えればいいけど
(edited)
Avatar
koher 02-Aug-19 02:45 AM
Class Existential Container は参照型だけ考えればいいんじゃない? (edited)
Avatar
omochimetaru 02-Aug-19 02:45 AM
Swiftは値型を値的性質のままで、protocolの多重継承とany protocol型へのアップキャストをやってるので
02:46
ああ、あくまでClass ECの話か。
Avatar
koher 02-Aug-19 02:46 AM
うん、 Opaque Existential Container は別として、 Class Existential Container が Witness Table を保持するのはなぜかって疑問。
Avatar
omochimetaru 02-Aug-19 02:46 AM
そのほうが速いからじゃないですかねえ
Avatar
koher 02-Aug-19 02:47 AM
じゃあ Java がペアで持ってないならなぜ速い方法を選ばなかったのか。まずペアで持ってないところを確認した方が良さそうだけど。
02:47
なにかの言語仕様の違いがそうさせてるのか、
02:47
それとも後発だからより良い方法が見つかったのか、
02:48
ユースケースの違いで 16 バイトの領域を使ってもパフォーマンスをとった方が良いということなのか、
Avatar
omochimetaru 02-Aug-19 02:50 AM
Swiftのほうが後発だから単純に思いつかなかったとか パフォーマンスを捨ててるとしたら、ありえそうなのは実装をシンプルにしたかったとか? thisポインタ一個のまま扱って、ランタイムリフレクションでメソッドを探すだけであれば、例えばGC実装とかでそのデータ構造の考慮はいらないですね (edited)
Avatar
koher 02-Aug-19 02:50 AM
2.6.1. Local Variables A single local variable can hold a value of type boolean, byte, char, short, int, float, reference, or returnAddress. A pair of local variables can hold a value of type long or double.
https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-2.html#jvms-2.6.1
Avatar
omochimetaru 02-Aug-19 02:51 AM
でもインターフェースアクセスのたびにメソッドの探索をしてたら重すぎるから、アップキャストテーブルとのペアはもってそうだけどなあ
Avatar
koher 02-Aug-19 02:51 AM
メソッド探索まではしてないんじゃない?
Avatar
omochimetaru 02-Aug-19 02:51 AM
インターフェース対応テーブルリストからのテーブル検索かな。
Avatar
koher 02-Aug-19 02:51 AM
各インタフェース用の vtable を持ってたら、 i 番目のテーブルをとってくるところは
02:52
1 ステップ余計に必要だけど、 O(1) には変わらないだろうし。
Avatar
omochimetaru 02-Aug-19 02:52 AM
え、1にはできないのでは
02:53
i番目がいくつかがわからないから
02:53
検索が必要です
Avatar
koher 02-Aug-19 02:53 AM
えっと、そこを線形探索してても、 implement されたインタフェースの数はメソッドの数と比べて小さく定数とみなせると思うし、
Avatar
omochimetaru 02-Aug-19 02:54 AM
メソッドの数と比べる意味がわからんです
02:55
だいたいのコードで、
// A はinterface void foo(a A) { a.hoge(); a.fuga(); a.piyo(); }
Avatar
koher 02-Aug-19 02:55 AM
ああ、メソッドを線形探索する話をしてるわけじゃないのか。
Avatar
omochimetaru 02-Aug-19 02:55 AM
↑こうなってたら、hoge,fuga,piyoの呼び出しのたびにその検索が生じる。
Avatar
koher 02-Aug-19 02:55 AM
あとは、効率が良いかどうかは別として、辞書的に今求めてるインタフェースに対応した vtable を O(1) で引くこともできるんじゃない?
Avatar
omochimetaru 02-Aug-19 02:55 AM
hogeとかの内容によっては、メソッド本体よりテーブル検索のほうが重い。
02:56
まあ辞書にはできますね。
02:56
計算量という意味ではそうだけど、それも処理本体に比べたらオーバーヘッドでかすぎると思いますけど・・・
Avatar
koher 02-Aug-19 02:56 AM
でも実装してるインタフェースなんて大した個数なさそうだから線形探索した方が速そうな気が。実質的に 1, 2 ステップ増える程度じゃないのかな? (edited)
Avatar
omochimetaru 02-Aug-19 02:58 AM
ArrayListでも すべての実装されたインタフェース: Serializable, Cloneable, Iterable<E>, Collection<E>, List<E>, RandomAccess このくらいですね
Avatar
koher 02-Aug-19 02:58 AM
Iterable > Collection > List あたりの継承関係にあるのはまとめられそう
Avatar
omochimetaru 02-Aug-19 02:59 AM
僕の感覚だと6ステップぐらいはかかっちゃう気がします。
02:59
Swiftはそこを理論上最速になるつくりで実装してると思う。 (edited)
Avatar
norio_nomura 02-Aug-19 03:03 AM
そうか、動的チェックのコードを見ないといけないのか。
動的チェックは_swift_dynamicCastが担ってて、実装はこれ。 https://github.com/apple/swift/blob/master/stdlib/public/runtime/Casting.cpp#L2271
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
Avatar
omochimetaru 02-Aug-19 03:05 AM
少なくとも
case MetadataKind::Existential: return _dynamicCastToExistential(dest, src, srcType, cast<ExistentialTypeMetadata>(targetType), flags);
03:05
このフローの内部で、Protocol Witness Tableの取り出しをやるはずですね。
03:05
Existential Containerの中にPWTを格納しないといけないので。
Avatar
koher 02-Aug-19 03:05 AM
- invokevirtual invokes an instance method of an object, dispatching on the (virtual) type of the object. This is the normal method dispatch in the Java programming language. - invokeinterface invokes an interface method, searching the methods implemented by the particular run-time object to find the appropriate method.
https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-2.html#jvms-2.11.8
Avatar
omochimetaru 02-Aug-19 03:07 AM
searching the methods とは書いてあるけど、そのへんは、JVM規格側なんで、
03:07
実際の今のモダンなVMがどうなってるかとは、わからなそう。
03:07
Javaは特にバイトコード規格と実装の分離を歴史的にがんばってるから、なおさら。 (edited)
Avatar
koher 02-Aug-19 03:08 AM
さっきの
A single local variable can hold a value of type boolean, byte, char, short, int, float, reference, or returnAddress.
からは、ペアになってなさそうな感じがする。
(edited)
Avatar
omochimetaru 02-Aug-19 03:09 AM
その「reference」が、常に一通りのポインタ1個でなければならないとは、言ってないんじゃないですかね?
Avatar
koher 02-Aug-19 03:09 AM
まあそうだけど、クラス型とインタフェース型変数で区別されてたらそこに列挙されてそうじゃない?
Avatar
omochimetaru 02-Aug-19 03:10 AM
う〜ん。まあそうですが、証拠にはならないと思います。
03:11
どこまでの議論をして何を断じたいのかにはよりますが、OpenJDKプロジェクトとかならオープンソースだし、 OracleもOpenJDKに乗っかったから、
03:11
そこを読みに行くのが一番正しい情報が得られると思います。
Avatar
koher 02-Aug-19 03:11 AM
うん、これだけで確証は得られないから「なさそうな感じ」。
03:12
仕様じゃなくて実装としてしか存在しなさそうかぁ。
03:12
ちょっと落ちます。
Avatar
koher 02-Aug-19 04:16 AM
reference 型の値はオブジェクトへのポインタって書いてあるから、やっぱ単にポインタ一つを保持してるだけじゃないかな?
The Java Virtual Machine contains explicit support for objects. An object is either a dynamically allocated class instance or an array. A reference to an object is considered to have Java Virtual Machine type reference. Values of type reference can be thought of as pointers to objects. More than one reference to an object may exist. Objects are always operated on, passed, and tested via values of type reference.
https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-2.html#jvms-2.2
Avatar
omochimetaru 02-Aug-19 04:17 AM
フーム・・・
Avatar
koher 02-Aug-19 04:19 AM
こっちでは reference 型を三つに分けてるけど interface のときの中身には詳しく触れられてないなぁ。
2.4. Reference Types and Values There are three kinds of reference types: class types, array types, and interface types. Their values are references to dynamically created class instances, arrays, or class instances or arrays that implement interfaces, respectively. An array type consists of a component type with a single dimension (whose length is not given by the type). The component type of an array type may itself be an array type. If, starting from any array type, one considers its component type, and then (if that is also an array type) the component type of that type, and so on, eventually one must reach a component type that is not an array type; this is called the element type of the array type. The element type of an array type is necessarily either a primitive type, or a class type, or an interface type. A reference value may also be the special null reference, a reference to no object, which will be denoted here by null. The null reference initially has no run-time type, but may be cast to any type. The default value of a reference type is null. This specification does not mandate a concrete value encoding null.
https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-2.html#jvms-2.4
(edited)
04:20
参照だとは書かれてるか。
04:22
reference 型の値は reference だってトートロジーっぽいな・・・。さっきの文と合わせて考えるとこの reference は単一のポインタと考えて良さそうだけどいまいち確信が持てない・・・。
04:22
#other-lang でやった方がいい気がしてきた。
Avatar
omochimetaru 02-Aug-19 04:26 AM
改めて. 言語処理系好きのためのslackを作りました.すでに初学者から強い方まで色々な人が参加してます: https://t.co/MDWx2TTOgy
Retweets
145
Likes
379
04:26
↑ここで聞けば知ってる人が居るかも。 (edited)
🙏 1
Avatar
norio_nomura 02-Aug-19 05:24 AM
- __TEXT,__swift5_protoセクションにprotocol conformance descriptorへのポインタが列挙されてる。 - protocol conformance descriptorには以下 が含まれる。 - protocol descriptorプロトコル - nominal type descriptorそのプロトコルに準拠する型。メタデータとは別 - witness tableその型がプロトコル準拠するに必要なwitness一覧 - nominal type descriptorにはメタデータへのポインタが含まれる。 これらのデータを元に、swift_conformsToSwiftProtocolは渡されたメタデータが準拠するプロトコル情報を探してきてくれる。実装はこちら。 https://github.com/apple/swift/blob/swift-5.1-branch/stdlib/public/runtime/ProtocolConformance.cpp#L544-L608 (edited)
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
05:28
* frame #0: 0x00000001012f3d13 libswiftCore.dylib`swift_conformsToSwiftProtocolImpl(… frame #1: 0x00000001012f3a56 libswiftCore.dylib`swift_conformsToProtocol [inlined]… frame #2: 0x00000001012f3a11 libswiftCore.dylib`swift_conformsToProtocol [inlined]… frame #3: 0x00000001012f3a11 libswiftCore.dylib`swift_conformsToProtocol… frame #4: 0x00000001012c4efa libswiftCore.dylib`swift::_conformsToProtocol… frame #5: 0x00000001012c8e07 libswiftCore.dylib`_conformsToProtocols… frame #6: 0x00000001012c849e libswiftCore.dylib`_dynamicCastToExistential(…
(edited)
05:29
これならば、witness tableへのポインタ持ちたくもなる。
Avatar
omochimetaru 02-Aug-19 05:31 AM
「これならば」ってのは、データ構造を手繰るステップ数がかかるから、高速化のためにって意味ですよね?
Avatar
norio_nomura 02-Aug-19 05:32 AM
そう。
🙂 1
Avatar
norio_nomura 02-Aug-19 06:21 AM
otool -l /usr/lib/swift/libswiftCore.dylibで見る__TEXT,__swift5_protoのサイズは0x1288バイトで、含まれるprotocol conformance descriptorの数は 4744/8=593
Section sectname __swift5_proto segname __TEXT addr 0x0000000000379758 size 0x0000000000001288 offset 3643224 align 2^2 (4) reloff 0 nreloc 0 flags 0x00000000 reserved1 0 reserved2 0
(edited)
Avatar
omochimetaru 02-Aug-19 06:25 AM
型の数がわかれば、一つの型の平均のプロトコル数がわかりますね
Avatar
norio_nomura 02-Aug-19 06:28 AM
YamsのテストYamsPackageTestsだとサイズ0x5a4でprotocol conformance descriptorの数は180
Avatar
norio_nomura 02-Aug-19 08:45 AM
型の一覧は__swift5_typesですね。
Section sectname __swift5_types segname __TEXT addr 0x000000000037a9e0 size 0x000000000000065c offset 3647968 align 2^2 (4) reloff 0 nreloc 0 flags 0x00000000 reserved1 0 reserved2 0
Avatar
omochimetaru 02-Aug-19 08:46 AM
Avatar
norio_nomura 02-Aug-19 08:46 AM
0x65c / 8 = 203個 (edited)
08:47
どこのセクションに何があるかはここ (Mach-Oバイナリの場合) https://github.com/apple/swift/blob/master/stdlib/public/runtime/ImageInspectionMachO.cpp#L32-L45 (edited)
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
Avatar
omochimetaru 02-Aug-19 08:54 AM
この辺、バイナリのセクション名になってるの面白い
08:54
実行ファイルのそのへんのデータ構造を普通に言語機能のために使ってしまうの驚いた
Avatar
norio_nomura 03-Aug-19 04:07 AM
Class Existential Container が Witness Table を保持するのはなぜかって疑問。
これ、今更だけど、 https://github.com/apple/swift/blob/master/docs/ABI/TypeLayout.rst#class-existential-containers
Note that if no witness tables are needed, such as for the "any class" type protocol<class> or an Objective-C protocol type, then the only element of the layout is the heap object pointer.
って注意書きがあるね。プロトコル制約がある時だけwitness tablesを持つ。
(edited)
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
04:08
指定してるプロトコル制約が、指定したクラスが準拠してるプロトコル全てと同一でない場合は、別途witness tableを持つしかない、という当然の帰結になるのでは。
04:08
速度とか関係なく。 (edited)
Avatar
koher 03-Aug-19 05:09 AM
今の Swift の実装でメタデータからメソッドにアクセスできるかどうかと、そのような実装をすることができるかは別問題ですよね?後者を採用しなかった理由としてパフォーマンスというのはあり得るんじゃないでしょうか。
Avatar
norio_nomura 03-Aug-19 05:18 AM
「Class Existential Containerがプロトコル制約を持つ」を、witness tableを持たせる以外で表現してメンバを使う際にはメタデータからwitness tableを検索する様にしなかった理由、って事ですか?
Avatar
koher 03-Aug-19 05:30 AM
そうですね。昨日の会話では確証は得られませんでしたが、 Java 等ではそうなってるんじゃないかと思ってます。
Avatar
norio_nomura 03-Aug-19 05:37 AM
なるほど、そういう実装との比較ならば、今の実装を選択したのはパフォーマンスが理由だと思います。
Avatar
koher 03-Aug-19 06:00 AM
そこの選択が分かれた理由が言語仕様による特性の違い(たとえば Swift は多数のプロトコルを conform させる傾向があり、よりパフォーマンス上のデメリットが大きい)とかがあるとおもしろそうだと考えてました。
Avatar
koher 06-Aug-19 05:17 PM
Generalized Existential が導入されて、一部の associated type だけ指定された場合、指定されなかった associated type は、戻り値で使われた場合は Any 、引数で使われた場合は Never になるんでしょうか?
protocol Animal { associatedtype Foo associatedtype Bar func foo() -> Foo func bar(_ x: Bar) -> Bar } struct Cat: Animal { func foo() -> Int { ... } func bar(_ x: Bool) -> Bool { ... } } struct Dog: Animal { func foo() -> Int { ... } func bar(_ x: String) -> String { ... } } let animal: any Animal<Foo == Int> = Bool.random() ? Cat() : Dog() print(type(of: animal.foo)) // () -> Int print(type(of: animal.bar)) // これは (Never) -> Any になる?
Avatar
tarunon 07-Aug-19 03:54 AM
set getなvarとかどうなるんでしょ?アクセスできなくなる気もする
Avatar
omochimetaru 07-Aug-19 03:56 AM
それが絡んだメンバはアクセスできないか、
03:56
AnyCollectionのIndexと同じで、それもまたAnyになって、
03:56
書き込みアクセスの時に、実態のassociatedtypeにダウンキャスト、型が違ったらクラッシュ
03:57
とかが考えられますね
03:57
protocol Animal { associatedtype Foo } なら Any で、 protocol Animal { associatedtype Foo : P } なら any P
03:59
型安全(実行時クラッシュ無し)にするなら、CovarianceポジションはAny, ContravarianceポジションはNeverにするしかない。(associatedtypeにプロトコルついてるなら境界になる
Avatar
koher 07-Aug-19 11:39 PM
set getなvarとかどうなるんでしょ?アクセスできなくなる気もする
setget で型がずれちゃいますよね。ただ、ある引数が Never ってアクセスできないことを意味しているとも考えられて、 setNever == readonly と解釈すればおかしくないかも。
Avatar
omochimetaru 08-Aug-19 01:31 AM
setが潰れると、any PがPを満たせなくなっちゃいますね
01:32
まあ今も、Ext. PはPを満たさないので、そっちに寄せるのもありですが
01:33
実行時エラーを許容してでもPを満たさせる方が、 既存のAnyCollectionなどには近い設計になるのでどっちの路線もありだと思います
01:34
あ、てか、例の新マニフェストによると
01:34
デフォルトでは違反になるものは生成されなくて
01:35
自分でextension any P : P としてやって、違反してたやつを無理やり自分で実装するとself conformが得られる
01:35
ってスタイルが提案されてたな
01:35
それだとユーザーの意思で選択できて良さそう (edited)
Avatar
koher 08-Aug-19 04:02 PM
any Pset がつぶれることと any PP を満たすことは両立できるんじゃないかな?たとえば↓のコードで、 getSetValuefoo を渡すときに existential container を分解して特殊化されてない版を実行させることに問題はなくない?
protocol Foo { associatedtype Value var value: Value { get set } } struct Bar: Foo { var value: Int } func getSetValue<F: Foo>(of foo: F) -> F { var foo: F = foo let value: F.Value = foo.value // get foo.value = value // set return foo } var foo: any Foo = Bar(value: 42) let value: Any = foo.value // foo.value = value // NG foo = getSetValue(of: foo)
Avatar
omochimetaru 09-Aug-19 01:11 AM
たしかに。それは正しいですね。 そうか、existentialのassociated typeは、アイデンティティがextのインスタンスに紐付いたopaque typeになりますね。 ORTはアイデンティティが関数宣言に紐付いているけど、これは値一つに対して固定される型だ。
Avatar
omochimetaru 04-Sep-19 01:10 AM
For a bit of background this stems from a bug I (and a number of other people) have reported on bugs.swift.org, the original being here: https://bugs.swift.org/browse/SR-103. The Current Situation For context let's start by looking at basic class inheritance, something we al...
01:11
protocolのデフォルト実装が親クラスのvtableにエントリを作らない問題のスレ
01:12
スレの中で過去スレが3つリンクされてるほどの根深いテーマ
Avatar
tarunon 04-Sep-19 01:12 AM
お、伸びてる
01:13
classとprotocolの両方の挙動に深い理解を以って初めてわかる動きだからなぁ
Avatar
omochimetaru 04-Sep-19 01:13 AM
レス14で提示されてるexistentialにアップキャストするパターンは初めて見たけどこれ見ると何が起きてるかわかりやすい
01:16
親クラスに対するプロトコルPの後付けと、サブクラスBの定義を別モジュールから行った場合には、どうしてもクラスAのvtableは書き換えられないから
01:17
どうにもならない気がする
01:19
実装できないから解決しなくて、でもハマる人が出てくるから話題が繰り返してるんだと思うけど
01:20
なんか良い落としどころはないんかなあ
Avatar
tarunon 04-Sep-19 01:20 AM
protocol extensionを含んだprotocolを「classの宣言時に定義」した場合にprotocol extensionをvtableに載せる、だと
01:21
framework問題も解決しつつ整合性が取れそうに思える
Avatar
omochimetaru 04-Sep-19 01:21 AM
それは1つの答えだけど、先付けと後付けで動きが変わるっていう新しい問題が新たに発生しちゃう
Avatar
tarunon 04-Sep-19 01:22 AM
それはそれでいいんじゃないか
Avatar
omochimetaru 04-Sep-19 01:22 AM
余計難しくなってるようにも思える
Avatar
tarunon 04-Sep-19 01:22 AM
classはextensionに書いたメソッドをoverrideできない(objc除き)という規則もあるので
01:23
受け入れやすいと思うよ
01:23
一貫してると思う
01:23
ただ、現状のprotocol extensionは上記extensionの括りに含みます、というのも
01:23
それはそれで一貫してはいる
Avatar
omochimetaru 04-Sep-19 01:24 AM
クラスのextensionがオーバーライドされない現象は、 サブクラス側でoverride修飾子が付かない事でハッキリしてて
01:25
それが受け入れられるなら、今のプロトコルの挙動も受け入れられるような気がする。
Avatar
tarunon 04-Sep-19 01:25 AM
まあなんかoverride非表示じゃなくて
01:25
コンパイルエラーにした方が良いとは思うけどw
01:25
今のルールにするにしても
Avatar
omochimetaru 04-Sep-19 01:26 AM
検出できる限りはエラーで止めるのは良さそう
01:26
検出できないけどこの現象が起きる穴が気になるけど、、、
Avatar
tarunon 04-Sep-19 01:27 AM
framework超えで違反起きた場合も一律エラーで良さそう
Avatar
omochimetaru 04-Sep-19 01:29 AM
例えば、AとPとBがそれぞれ別のフレームワークの場合は?
Avatar
tarunon 04-Sep-19 01:29 AM
最後にimportしてるフレームワークで破綻検知できるからそこで落ちれば良さそう
Avatar
omochimetaru 04-Sep-19 01:31 AM
Bがfuncを定義しようとしたとき、同じ名前のメソッドが親クラスのprotocolでデフォルト実装がついていたら禁止するってことね
Avatar
tarunon 04-Sep-19 01:31 AM
後付けで破綻が起きてもエラー
Avatar
omochimetaru 04-Sep-19 01:31 AM
じゃあ、 AKit <- BKit <- PKit の順番でimportが依存してる場合は?
01:31
Bの時点だとAはPによる問題を抱えていないから見えない。
Avatar
tarunon 04-Sep-19 01:32 AM
Pを入れるところで発覚するはず
Avatar
omochimetaru 04-Sep-19 01:32 AM
なるほど・・・そうだよね、で、最後が
01:32
AKit <- BKit と AKit <- PKit というBkitとPKitが独立に実装されていて、 Appが BKit <- App, PKit <- App って
01:32
両方取り込む場合は?
Avatar
tarunon 04-Sep-19 01:33 AM
importがエラーになればオケ
Avatar
omochimetaru 04-Sep-19 01:33 AM
マジ?
01:33
BKitもPKitも独立でビルドできているのに
01:33
まとめて取り込もうとするとそれが拒否されるって現象は
01:33
いいのかな・・・
Avatar
tarunon 04-Sep-19 01:33 AM
そういう挙動は許されるべきだと思う
Avatar
omochimetaru 04-Sep-19 01:34 AM
「同時に取り込む互換性の無い2つのモジュール」って概念が爆誕するのか
Avatar
tarunon 04-Sep-19 01:34 AM
protocol extensionで同名のfuncを別々のframeworkに生やして二つimportしたら破綻する
01:34
今でもそうじゃないの
Avatar
omochimetaru 04-Sep-19 01:34 AM
お、そうだっけ
01:34
今どうなるんだ?
Avatar
tarunon 04-Sep-19 01:35 AM
記憶が正しければその概念は既に存在したと思う、一回そのエラーを引いた記憶がある
Avatar
omochimetaru 04-Sep-19 01:35 AM
やってみるか
01:35
えーっと
Avatar
tarunon 04-Sep-19 01:35 AM
これコンパイルエラーにする時の問題は計算量が爆発しないかぐらいだと考えてるよ
Avatar
omochimetaru 04-Sep-19 01:35 AM
PKit に Pの素体が入ってて、 PXKit に Pのdefault impl x、 PYKitにPのdefault impl y が入ってて
01:35
AppからPXKitとPYKitを取り込むって形?
Avatar
tarunon 04-Sep-19 01:36 AM
そうだね
Avatar
omochimetaru 04-Sep-19 01:36 AM
計算量は爆発しないと思うよ
01:36
新たに取り込むモジュールのDeclの数nに対してO(n)のスキャンをするだけだから。
01:37
すでに取り込んだDeclはテーブルに入ってればO(1)で突合チェックできる。
Avatar
tarunon 04-Sep-19 01:37 AM
where句とかもあるけど大丈夫かね
01:37
まあ大丈夫か
Avatar
omochimetaru 04-Sep-19 01:37 AM
whereの場合はそもそもvtableとか無理よね?
Avatar
tarunon 04-Sep-19 01:37 AM
同じ問題は発生するよ
Avatar
omochimetaru 04-Sep-19 01:37 AM
あー、default implがwhereの場合か
01:38
あれ?それって実装分けられるんだっけ
01:38
できるか。
01:38
conditional conformanceが1つしかできないだけか。
Avatar
tarunon 04-Sep-19 01:38 AM
そう
Avatar
omochimetaru 04-Sep-19 01:39 AM
じゃあ今チェックしてるサブクラスが、親クラスの持ってるprotocol default implとの突合を見る時に、
01:39
そのdefault implがwhere付きならそれが有効化するのかどうかを見ないといけんのか。
01:39
まあ保守的に殺しても良い気がする・・・
01:39
それこそ混乱しそうな状況だし。
Avatar
omochimetaru 04-Sep-19 01:50 AM
Contribute to omochi/ProtoExConflictExp development by creating an account on GitHub.
01:50
できた
01:51
ちょっと思ったのと違う挙動だった
01:51
AppからPXKitとPYKitをimportした瞬間に
01:51
どちらのdefault implも消滅して
01:51
App.S の S : P が conformされてないよってエラーになった。
Avatar
tarunon 04-Sep-19 01:51 AM
なるほど
Avatar
omochimetaru 04-Sep-19 01:52 AM
片方だけimportすると、そっちがちゃんと入る。
01:52
このほうが被害が最小限でいいね
01:52
「対消滅が起きたこと」はなんらメッセージされないのがちょっと良くないと思ったけど。
01:53
同じ発想でピンポイントブロックするのは難しそうだなあ
01:53
PKitのdefault実装はすでにPKitの中のA conform Pで取り込まれちゃってるから
01:54
Appで何かを無効にすることで止められるものでもない
01:54
ま〜でも、う〜ん、import失敗するのが良いような気もするな
01:54
そしたらこのスレの連鎖を止められる
Avatar
omochimetaru 18-Sep-19 03:22 AM
var a = [1, 2, 3] func f(_ index: Int) { let b = Array(a[index...]) + Array(a[..<index]) print(b) } f(0) // [1, 2, 3] f(1) // [2, 3, 1] f(2) // [3, 1, 2]
03:22
↑関数fの実装に関して、簡潔に書いたらこうなったんですがパフォーマンスが悪そう どういうのがいいかな
Avatar
tarunon 18-Sep-19 03:30 AM
Array(a[index...] + a[..<index])にすると少しだけ良くなりそう
Avatar
omochimetaru 18-Sep-19 07:56 AM
あ、ArraySliceのまま結合できるのか。
Avatar
tarunon 18-Sep-19 09:41 AM
こういうプログラミング言語の特性も踏まえたパフォーマンスの話は面白いですね
09:41
.first(where:)をメソッドチェーンの末尾に使う場合はメソッドチェーンの開始に.lazyを入れると早くなる、とか (edited)
Avatar
koher 18-Sep-19 05:58 PM
そういうの、Haskellみたいな遅延評価だと強いですよねー。
17:59
循環については、 ArraySlice みたいな型を作ってラップして返すのが良さそう。
18:00
で、 Array になってほしい時だけ選択的にコストを払って変換。
18:02
CollectionSubSequence みたいに associatedtype 持っててもおもしろそう。循環コレクションから循環コレクションとっても循環コレクションのままでいいので二重にラップされないみたいな。
18:03
RangeSubSequenceRange 自身なように。
18:04
もう一つはlazy 方式かなぁ。
Avatar
omochimetaru 18-Sep-19 06:15 PM
一番動作効率がいいのはCollectionをラップする型を作る方法ですねー
Avatar
koher 18-Sep-19 10:51 PM
ShiftedArray<Element> とかより Shifted<Base: Collection> とかの方がいいかな?名前は別として。
22:52
IndexInt の縛りがないと難しいかな。
Avatar
omochimetaru 19-Sep-19 03:19 AM
startIndex, endIndex, advanceがあれば、ラップした結果をSequenceにすることはできそう。 (edited)
03:20
CollectionならoffsetbyがあるからCollectionにもできるかな?計算量要件を満たすかわからん
Avatar
koher 19-Sep-19 06:03 AM
そこが O(1) にできるなら StringIndexInt でいいんじゃない?
Avatar
omochimetaru 19-Sep-19 06:05 AM
あ、負荷がかかるのは最初にShiftedArrayを生成するときだけだから
06:05
普通にCollectionにできそう。
06:05
Indexをadvanceするところは、同じように内部Indexを1つadvanceするだけだし、
06:05
巡回してstartIndexに戻るところは内部collectionから取得できるので。
06:06
というか、「どこから始めるか」をShiftedArrayのinitで受け取るだろうから、
06:06
すでに最初のオフセット負荷は完了しているな。
Avatar
koher 19-Sep-19 10:27 AM
Shifted を生成する部分を O(1) にしたいのではなく?
Avatar
omochimetaru 20-Sep-19 01:47 AM
例えばStringの場合、 Shifted(str, str.index(str.startIndex, offsetBy: 4)) とか書かざるを得ないと思うので
01:48
Shifted自体は渡されたCollectionとIndexを受け取って生成するだけじゃないすかね
01:49
Shifted(str, 4) として 内部で同じことをすることはできるけど、まあその場合もこれ以上早い方法は無いし。
Avatar
koher 20-Sep-19 02:59 AM
たとえば Shifted<String> があったとして、その subscript のインデックスはずらして循環させた String と同じものである必要があるよね?そのインデックスを生成する手間を考えたら、そのシフトされた String を生成した方が速くない?なので、 インデックスが Int 以外のときは Shifted が不要な気がする。より正確に言えば、 Int64 とか O(1) で計算できるやつはできるけど、そこはサポートしなくてよいかと。
Avatar
omochimetaru 20-Sep-19 03:58 AM
その subscript のインデックスはずらして循環させた String と同じものである必要があるよね
そこはそうとは限らないような? Elementは同じものを期待してるけど、Shifted.Indexで良い
そのシフトされた String を生成した方が
「方が」が指してる2つはそれぞれどういう方式ですか?
インデックスが Int 以外のときは Shifted が不要な気がする
"abcd" から "cdab" を得るために必要です
(edited)
Avatar
koher 21-Sep-19 03:00 AM
シフトする API は必要として、 String で事前に O(N) 支払うならその API が返す型は String でよくない?
Avatar
koher 21-Sep-19 03:08 AM
Collectionassociatedtype ShiftedCollection: Collection where ShiftedCollection.Element == Self.Element, ShiftedCollection.Index == Self.Index を付けて func shifted(by: Int) -> ShiftedCollection として、 ArrayShifted<Array<Element>>StringString を返すのがいいかなぁ。 shifted が O(1) か O(N) かが型によって変化するのが微妙かな。
Avatar
omochimetaru 25-Sep-19 05:11 AM
ああ、Shited型を作るんじゃなくてassociatedtypeにするとStringから直接Stringが得られるって事か。
05:11
でもStringを再構成よりインデックスだけずらしてるラッパーの方が動作は軽そう。
05:13
ShitedがCollectionだと思うんで、 String(Shifted(str, ...)) で明示的に再構成すれば良い気もします。
Avatar
koher 26-Sep-19 06:19 AM
たしかに計算量のオーダーは変わらなくてもラッパーならバッファは一つで済むし計算も軽そうだね。
06:21
associatedtypeなら、Shiftedをさらにshiftしたときにネストしなくて良い(ArraySliceがネストしないのと同じ)というのはありそう。
Avatar
omochimetaru 18-Oct-19 02:55 AM
Swiftのrethrowsに条件をつけられるようになったら良さそう。 https://t.co/ir6fOzVoU0
02:56
protocol Iterator { associatedtype Element associatedtype Failure: Error func _next() throws -> Element? } extension Iterator { func next() throws -> Element? { try _next() } } // 例外飛ばない版 // 本体の定義が`_next`なのは、もし`next`だとここで自己再起しちゃうから。。 extension Iterator where Failure == Never { func next() -> Element? { try! _next() } } // こういう仕組みが必要なのかもしれない // iterator.nextの呼び出しから例外が飛ばないことがXの型からわかるとき、 // dropCからも例外を飛ばないということを宣言したい // rethrows句自体はすでにあるけど、クロージャを渡した場合に限られた機能なので、 // これを拡張する。 func dropC<X: Iterator>(iterator: X, n: Int) rethrows(from iterator.next) { for _ in 0..<n { _ = try iterator.next() } }
03:00
↑これどうかしら
Avatar
tarunon 18-Oct-19 03:05 AM
クロージャーを渡すのはダメなの?
03:07
こういう時は値ではなくクロージャーを渡すようにしてる。結局本質的に欲しいのは値ではなかったりするので
03:08
例えば他の例ではinitできることを保証するprotocolも便利だけど場合によってはinit関数それ自体を渡したほうがいいケースが結構ある (edited)
Avatar
omochimetaru 18-Oct-19 03:29 AM
Iteratorだとメソッドがシンプルすぎるからアレだけど、前提として、Errorを型にもつジェネリックな型を扱う場合において、それを使うライブラリを書く時にwhere Neverなオーバーロードを避けたくなるよね、という話です
03:30
実例でいうとCombineのStreamとか。あ、でもあれは非同期だからthrowsが絡んでこないな。 (edited)
03:30
Swiftc合宿 2019/09/28. Contribute to omochi/SwiftTypeInferenceHandsOn development by creating an account on GitHub.
03:30
↑最近感じた実例をもう一つあげると、このTypeWalker.findは
03:30
渡してるpreWalkが例外を投げないから、walk自体も例外を投げないんだけど、
Avatar
tarunon 18-Oct-19 03:31 AM
どちらかというとthrowsの側にwhereがあれば十分なのかな (edited)
Avatar
omochimetaru 18-Oct-19 03:31 AM
一度throwsのついてるvisitメソッドの呼び出しを経由するからrethrowsで表明できなくて
03:31
ああ、throwsになる理由をwhereで示すってことよね?
03:31
rethrows(from)のアイデアはまさにそれです。
Avatar
tarunon 18-Oct-19 03:31 AM
protocolとしてthrows funcを定義する時に条件付きにできれば
Avatar
omochimetaru 18-Oct-19 03:31 AM
あ、そっちか。
Avatar
tarunon 18-Oct-19 03:31 AM
rethrows側も解釈できるようになるはず
03:32
ただまあなんかGenericだとthrowsに倒れざるを得ないのはわかる、というのと
Avatar
omochimetaru 18-Oct-19 03:32 AM
GitHub Gist: instantly share code, notes, and snippets.
03:33
dropBみるとわかると思うんだけど、
Avatar
tarunon 18-Oct-19 03:33 AM
実は無理やり朋友関係を見出してそれをGenericsに無理に展開しようとした段階で理論破綻してるのでは?という気もしている
Avatar
omochimetaru 18-Oct-19 03:33 AM
多分そっちがわだとできないんだよね
03:33
やりたいのはdropB自体がthrowsかどうかってことなので
03:33
その本文のnext()がthrowsかどうかから伝搬させようとしたら
03:33
「そもそもthrowsに合わせて中でtryをする」っていう縛りが
03:34
壊れちゃう気がする
03:34
うーん、関数型も(A) -> RってようはFunction<A, R>って型のfunc call()を呼んでるだけだからなあ。
03:34
関数型だけ特別なんじゃなくて、rethrowsが関数型に特化してるので、それを汎用的なジェネリクス型に拡張すべきってアイデア。
Avatar
tarunon 18-Oct-19 03:35 AM
結論から言うとそういうときはResult使おうぜ、になるのでは
03:35
そうでもない?
Avatar
omochimetaru 18-Oct-19 03:35 AM
Result型で返してErrorの型をResultの中に入れていけばいいのはそうだね。
03:35
CombineでProviderモナドチェーンで書くのと同じ事になって
03:36
ResultモナドでのflatMapスタイルで書けば解決はする。
Avatar
tarunon 18-Oct-19 03:36 AM
最終的にResultから値を取り出すタイミングでerrorがthrowされるかNeverで無視されるか、と言うことになる
Avatar
omochimetaru 18-Oct-19 03:36 AM
でもflatMapスタイルを通常の制御スタイルでかけるのがthrowsの魅力なので、throwsの適用範囲を広げたいじゃん。
03:36
そうだね、あってる。>最終的に取り出すところ
Avatar
tarunon 18-Oct-19 03:37 AM
つまりErrorをassocに入れてthrow funcを書いたら protocol extensionにResult wrapperを書けばこの問題は本質的にクリアできる
Avatar
omochimetaru 18-Oct-19 03:37 AM
現状ならdropBみたいに2つ書くよりResultモナドに閉じ込めて書くほうがマシっちゃマシね
03:37
でも.next()がResultで返ってきたら萎えるでしょw
Avatar
tarunon 18-Oct-19 03:37 AM
流石にthrow-rethrowにこれを展開するのは無理筋な気もしていて、これは餅は餅屋で良いのではないでしょうか (edited)
Avatar
omochimetaru 18-Oct-19 03:38 AM
うーむ。
Avatar
tarunon 18-Oct-19 03:38 AM
いやだから、nextそれ自体はthrow funcで書かれていて
03:38
そのラッパーが用意されていれば、rethrows展開したいときはResultを使うことができるようになる、という感じ
Avatar
omochimetaru 18-Oct-19 03:38 AM
ああ、なるほど。
03:39
直接使う用にthrowsとwhere Neverなno throwがあって、
Avatar
tarunon 18-Oct-19 03:39 AM
そうそうそう
Avatar
omochimetaru 18-Oct-19 03:39 AM
ジェネリックなライブラリを実装するようにResultのインターフェースもあるのね。
Avatar
tarunon 18-Oct-19 03:39 AM
カンのペキな気がする〜
Avatar
omochimetaru 18-Oct-19 03:39 AM
現状のベストプラクティスではあるね。
Avatar
hironytic 18-Oct-19 03:43 AM
話がそれちゃうけど、この例のFailureがNeverのときの具体的な型って、next()はthrows付きとthrowsなしの2つがオーバーロードされた感じになってるんですか?それともなしのほうだけになってる?
Avatar
omochimetaru 18-Oct-19 03:44 AM
2つのオーバーロードですね
03:44
それで、where付きのほうがジェネリックシグネチャが厳しいので、両方いけるときはそっちが選ばれる
03:44
呼び出し側でtryをつけてるかどうかはオーバーロードの結果選択に影響しない気がする。
Avatar
hironytic 18-Oct-19 03:45 AM
ということは、dropCはXの型によって、実際に呼び出す先が変わる?
03:46
あ、 rethrows from ができたとしての話。
Avatar
omochimetaru 18-Oct-19 03:46 AM
あー、たしかに、このままだとdropCのなかで呼ぶnextが固定されちゃいますね
03:46
tarunonのいうとおり、protocol側にも条件が必要そうだ。
Avatar
tarunon 18-Oct-19 03:47 AM
なるほど
Avatar
omochimetaru 18-Oct-19 03:47 AM
func next() throws(when Failure!=Never) -> Element?
03:47
みたいにnextもオーバーロードするんじゃなくて、throws自体が変化するっていうスタイルでひとまとめにかかないとな。
03:48
あ、ちがう、そこは func next() throws(Failure) -> Element? こうかければいいんだ。
03:48
typed throwsですね。
Avatar
tarunon 18-Oct-19 03:48 AM
Resultある今それは難しそうだw
Avatar
omochimetaru 18-Oct-19 03:48 AM
じゃあdropCも同じだ。これでいいじゃん。
func dropC<X: Iterator>(iterator: X, n: Int) throws(X.Failure)
(edited)
Avatar
hironytic 18-Oct-19 03:49 AM
なるほど
Avatar
omochimetaru 18-Oct-19 03:50 AM
そうか、Javaのtyped throwsは
03:50
throws句にジェネリックパラメータタイプを書けないからダメだったんだな
03:50
具体的なExcepition型を列挙しないといけない
03:50
そこをジェネリクス対応させればスッキリじゃん
Avatar
tarunon 18-Oct-19 03:50 AM
本質的にそれResultですよね…
03:51
多分だけどResultに糖衣用意してあげるほうが筋が良い気はしています
Avatar
omochimetaru 18-Oct-19 03:51 AM
それはそう。ていうか、throwsっていう文法機能が、エラーモナドの構文変換だから。
Avatar
tarunon 18-Oct-19 03:51 AM
do構文なんだよね、それが先に来て後からResult来たのはちょっとおもろい
Avatar
omochimetaru 18-Oct-19 03:52 AM
だからResult型の導入の時にErrorパラメータを付けるか議論が盛り上がったのだし。
03:52
むしろResultでErrorパラメータを付けてくれた今こそ
03:52
typed throwsの流れに期待はできる
Avatar
tarunon 18-Oct-19 03:52 AM
うーん私は
Avatar
omochimetaru 18-Oct-19 03:52 AM
ResultにErrorが無かったらCombineにもErrorが無くてそもそものストーリーが始まらなさそう
Avatar
tarunon 18-Oct-19 03:52 AM
Resultある環境ならそれに幾つかの糖衣を用意した方が筋はいい気はするのだよなぁ
Avatar
omochimetaru 18-Oct-19 03:53 AM
糖衣であると思っても差し支えなくない?
03:54
throws(Failure) を用意するのとどう違うん
Avatar
tarunon 18-Oct-19 03:55 AM
単純に実装の実現性と今の仕様からの差分の少なさの話で
Avatar
omochimetaru 18-Oct-19 03:56 AM
差分は少ないと思うよ これまでのthrowsthrows(Swift.Error)と同じ意味として互換性が得られる
Avatar
tarunon 18-Oct-19 03:56 AM
フーム
Avatar
hironytic 18-Oct-19 04:00 AM
まあ本当に糖衣になるのなら、throws 付き関数を try なしで呼んで結果を Result で受け取れてもいいように思いますが。
Avatar
tarunon 18-Oct-19 04:01 AM
私のイメージはそんな感じでした。逆も然りで、Result返り値でそれが出来るのもアリかなと
04:01
サブタイピングだと闇が発生するので、アサインのみ変換して許可とかになるかとは思いますが (edited)
Avatar
omochimetaru 18-Oct-19 04:01 AM
今は let a = Result { try f() } で包む必要があるね
04:01
暗黙変換じゃなくて明示的変換
04:02
糖衣であるっていうのがthrowsとResultの変換が暗黙である、って話になるなら、ちょっとまた別の論点そう
Avatar
hironytic 18-Oct-19 04:02 AM
Result が戻り値の関数を try 付きで呼ぶのも。
Avatar
omochimetaru 18-Oct-19 04:04 AM
あ、そうですね。現状だと try f().get() になるやつ。
Avatar
tarunon 18-Oct-19 04:04 AM
明示変換の方が良いのはそれはそう、なので
04:04
書き味がもう少し良くなれば良いかな
Avatar
omochimetaru 18-Oct-19 04:04 AM
うーん、そのへんはやっぱりいらない気がするなあ。
Avatar
hironytic 18-Oct-19 04:04 AM
throwsとResultが実質的に等価であるというのはそうなんですが、糖衣構文という話になると、糖を剥がした書き方もできるのが当然という気がするんですよね。
Avatar
omochimetaru 18-Oct-19 04:04 AM
Resultは非同期とかで値をキープしたいためのものであって、
04:04
エラーハンドリングを含むロジックを書くところで使うものではないような
Avatar
tarunon 18-Oct-19 04:05 AM
typed throwが無い今はそれの代替も含んでしまう
Avatar
omochimetaru 18-Oct-19 04:05 AM
typed throwsでdo-tryで書いて、最後にResultに明示的にしまえばいい。
04:05
はい、今はびみょ〜な状態。
Avatar
tarunon 18-Oct-19 04:05 AM
で、そうなってしまった以上、typed throwをそこに提案するのは難しいんじゃ無いかなと思うわけです
04:05
これは本質的にどちらが良いと言うよりは、人間がどのようにものを考えてしまうかと言う話で
04:06
議論を運ぶのは難しそうだなと言う肌感がある (edited)
Avatar
omochimetaru 18-Oct-19 04:06 AM
そこは大丈夫、フォーラムの議論とか意味ないから
04:06
コアチームがわかってればいい
Avatar
tarunon 18-Oct-19 04:07 AM
まあそれならいいんじゃがw
Avatar
omochimetaru 18-Oct-19 04:07 AM
あれの実態はコアチームが見落としがないように意見を集める場であって
04:07
議論の流れの雰囲気と結論はわりと独立しがち
04:07
これまで見てて良い意味で信頼してる
04:08
僕が提案するとしてそもそもの説得力のある文章がかけるかという問題はあるけど。
Avatar
tarunon 18-Oct-19 04:08 AM
Resultを使った今のベストプラクティスを踏まえた上でtyped throwの優位性を説ければ、良い提案になりそうな気がする
Avatar
koher 19-Oct-19 01:59 AM
@omochimetaru
そうか、Javaのtyped throwsは throws句にジェネリックパラメータタイプを書けないからダメだったんだな
Javaのthrowsは型パラメータ書けなかったっけ?問題はbottom typeがないことと、throwsにbottom type書いたら検査が起こらないようにする機能がないことじゃないかな?あと、単一の型パラメータでは複数の例外クラスのthrowsに対応できないからUnionもいる。
Avatar
masakihori 19-Oct-19 03:09 AM
func f() throws(BError) -> T let r = Result<T, AError> { try f() }
03:09
で、「あかんで」って言ってもらえるの便利だと思うけど
03:10
逆に
03:11
func f() throws(BError) -> T let r = Result { try f() } // 型パラメータ不要
03:11
もできる
Avatar
Kishikawa Katsumi 21-Oct-19 03:52 AM
そういえばJavaの例外がすごく嫌われて(その影響でなんとなくtry/catchが嫌われるのは)Javaは標準APIの例外の使い方が良くなかったからですね。 機能は今の言語と比べたら不足はしてるけどちゃんと設計されてたからAPIの例外がマトモだったらここまで嫌われることはなかった、はず。
Avatar
omochimetaru 21-Oct-19 03:53 AM
使い方が良くなかった
そう思います。 でもSwiftでいうところのtry!相当は欲しいですね。
03:54
ある文だけをRuntimeExceptionにするときに5行か6行かかる
03:54
あ、あと、throwsな関数の本文でどこから飛んでるかわからなくなるから、あんまり安心感が無いというのも。
03:54
例外型システムはよくできてるけど ・標準ライブラリの準拠の仕方が悪い ・構文サポートが弱い(markedでないのが良くない, REへの昇格が煩雑) の2つ欠点があると思います (edited)
Avatar
tarunon 21-Oct-19 03:55 AM
RuntimeException周りが一番キツイ印象
03:56
@koher@omochimetaru か忘れましたけど言及していたと思っていて、RuntimeExceptionがExceptionのサブタイプになってしまってる、っていうのと、その周辺の言語仕様との組み合わせでかなり辛い感じに仕上がってる気はするんですよね (edited)
Avatar
omochimetaru 21-Oct-19 03:56 AM
RuntimeExceptionがExceptionのサブタイプ
そこ自体は俺は正しいんじゃないかと思ってる
03:57
検査が不要な式 < 検査が必要な式 のはずだから。 Swiftの関数型も () -> Void is () throws -> Void でしょ。
Avatar
tarunon 21-Oct-19 03:58 AM
えっとね
Avatar
Kishikawa Katsumi 21-Oct-19 03:59 AM
その辺はJavaの時代はしょうがなかったし、そんなに問題はなかったと思う。
04:00
java.sqlパッケージとかそのへんがもうちょっとなんとかなってれば。。。という。 (edited)
Avatar
omochimetaru 21-Oct-19 04:00 AM
まあたしかに、他の言語の書き心地もそこまで良くなかったですね。
04:00
Rubyとかが書き心地に関しては切り開いたと思う。
Avatar
tarunon 21-Oct-19 04:01 AM
後思いつくのはRuntimeExceptionがNullPointerExceptionも含んでいるので、これが頻発する、とかかな
Avatar
omochimetaru 21-Oct-19 04:01 AM
NullPointerExceptionが検査例外じゃないとあまり意味ないのはそう
Avatar
Kishikawa Katsumi 21-Oct-19 04:01 AM
あと、Javaの例外はコールスタックを保存するので遅いから、通常のケースで使うべきじゃないんだけど、そういうのが標準APIにあったとか。 (edited)
Avatar
omochimetaru 21-Oct-19 04:01 AM
でもそのためにはnull safetyが入ってないと実装できないからどうしようもないw
Avatar
Kishikawa Katsumi 21-Oct-19 04:02 AM
そう ^JavaでNullPointerExceptionを検査例外にはできない。
04:02
すべての行がtryになる。
Avatar
omochimetaru 21-Oct-19 04:02 AM
もしやったとしても、いくらやってもunwrapできない(not null型がない)から
04:02
無限にtrycatchがひつようw
Avatar
Kishikawa Katsumi 21-Oct-19 04:02 AM
いや、NullPointerExceptionはSIGABORTと思えばいいんですよ。
Avatar
tarunon 21-Oct-19 04:02 AM
その当たりの辛さが重なった結果、検査例外は辛いとして認識されているのだと思う
Avatar
Kishikawa Katsumi 21-Oct-19 04:03 AM
JavaでNullPointerExceptionはキャッチしないわけだから、それはあまり関係ないんじゃないかな。
Avatar
tarunon 21-Oct-19 04:03 AM
検査例外は辛いと言ってる人の中には、Null safeじゃないのは辛いを意味している人も結構いるんじゃないかな
Avatar
omochimetaru 21-Oct-19 04:03 AM
たとえJavaの検査例外が良くできていたとしても、ヌルポで壊れちゃうのだと、結局安全な言語だと思えないから
04:03
検査例外のおかげで安全になった、って認識できない気がします
Avatar
Kishikawa Katsumi 21-Oct-19 04:04 AM
今の視点でいうとそう。
Avatar
omochimetaru 21-Oct-19 04:04 AM
正確には、検査例外で扱う範囲では安全、という状況は目指せたはずではあるけど
04:04
「ヌルポはまあ別枠でしょうがないよね」って気持ちのもとで
04:04
検査例外自体はいいものだよね、って思えた可能性はあるのかも。
04:05
僕はJava頑張ってたとき、ちょっとはそう思った気がする。
Avatar
Kishikawa Katsumi 21-Oct-19 04:05 AM
Javaが言ってた安全はポインタの演算がない、っていうので、 そのあと何年かして、イミュータブルとかNull安全とか、って感じじゃない? <=別の言語ね。 (edited)
Avatar
omochimetaru 21-Oct-19 04:06 AM
ああ、そうですね、Javaが掲げた安全は、未定義動作が生じないという意味の安全がでかくて
04:06
どんなにバグらせてもメモリからコード注入とかできなくて、ちゃんとマネージドな例外になっている、という意味での安全。
04:07
アプリが落ちるより、アプリのバグからクラックされる方がより怖いので、 そういう意味では、悪い状況のボトムラインはだいぶ上がったはず
Avatar
Kishikawa Katsumi 21-Oct-19 04:08 AM
でまあサーバで使うぶんにはNullPointerException起こっても500になるだけだから、、、ってのはありますね。
04:08
直すのは大変だけど。
Avatar
omochimetaru 21-Oct-19 04:09 AM
たしかに。RuntimeExceptionだろうがcatchできるのは良いところですね。
Avatar
koher 21-Oct-19 06:30 AM
@tarunon 僕も言ってますが @omochimetaru も↓で言ってますね。
検査例外すべてを補足しようとして、Exceptionのcatch節を書いてしまうと、それではRuntimeExceptionも捕捉してしまいます。
https://qiita.com/omochimetaru/items/c30f7a021fb9b8f0fa92#検査例外だけ捕捉するのが困難 >> RuntimeExceptionがExceptionのサブタイプ
そこ自体は俺は正しいんじゃないかと思ってる
これは意見が変わったの?
Swiftのエラーハンドリングは他のメジャーなプログラミング言語のどれとも異なる新しい仕様を持っています。特に、検査例外を持っているのですが、これはJavaで採用された以降はほとんどの言語で採用さ...
Avatar
omochimetaru 21-Oct-19 06:33 AM
「検査例外全てを補足したい」というニーズはあるけどそれができなくてRuntimeExceptionを巻き込む という問題意識は継続してます
06:33
「サブタイピングが間違っている」ってかいてましたっけ?
Avatar
koher 21-Oct-19 06:34 AM
というのも、Exceptionは検査例外ですが、そのサブクラスであるRuntimeExceptionは非検査例外だからです。
Avatar
omochimetaru 21-Oct-19 06:35 AM
それ自体は、キャッチしちゃう理由だから、嘘は言ってないんだよな・・・
06:35
どうするのがいいんだろうな Exception > CheckedException Exception > RuntimeException こうしておいたらよかったんじゃないか。
Avatar
koher 21-Oct-19 06:35 AM
うん、それだったらいいと思う。
Avatar
omochimetaru 21-Oct-19 06:35 AM
その上で、自分は、CheckedExceptionでまとめてキャッチを普段は使いたい
Avatar
koher 21-Oct-19 06:36 AM
でも、根っこにThrowableがあるし、Exceptionとは?ってならないかな?
Avatar
omochimetaru 21-Oct-19 06:37 AM
Exception is Throwableはおかしい気がしますね
06:37
Throwableなら検査は不要なのに
06:37
Exceptionを投げる関数はThrowableを投げる関数とみなせるはずなのに
06:38
そうみなした瞬間にExceptionのcatch強制する性質が消える
Avatar
koher 21-Oct-19 06:42 AM
throwsの後ろに書けるという性質と、throwできるという性質を分けて考えないといけなさそう。
Avatar
omochimetaru 21-Oct-19 06:43 AM
Throwableは書けない?
Avatar
koher 21-Oct-19 06:43 AM
Javaではその二つが両方Throwableで表してるけど。というか、検査例外と非検査例外が同じthrows/throwで表されてるのが良くないのかな。
06:45
throws Error とthrows Never 的サブタイピングを考えるとThrowableでまとめるのに無理がありそうって意味。
06:46
そうすると検査例外が親じゃないといけないけど、そしたら↑の非検査例外巻き込みが起こるから、別系統にして構文も変えるのが良さそう。
06:49
Swiftが非検査例外(Logic Failure)の構文をthrows/tryから分離したのは正しそうだなぁ。あとは、↓とかで非検査例外のハンドリングがサポートされれば…。 https://gist.github.com/lattner/31ed37682ef1576b16bca1432ea9f782#part-3-reliability-through-fault-isolation
Swift Concurrency Manifesto. GitHub Gist: instantly share code, notes, and snippets.
06:52
@Kishikawa Katsumi JavaのAPIの例外の使い方が良くないというのは僕もそうじゃないかと思ってましたが、 parseInt の NumberFormatException が非検査例外なのが飛び抜けてヤバいのに印象が引っぱられてて、他はそうでもないと思うようになりました。
Avatar
omochimetaru 21-Oct-19 06:52 AM
それで岸川さんが出した例がjava.sqlパッケージの話なのかと思いました
Avatar
koher 21-Oct-19 06:53 AM
https://docs.oracle.com/javase/tutorial/essential/exceptions/runtime.html このあたりの使い分けも Swift とあまり変わらなさそう。
This Java tutorial describes exceptions, basic input/output, concurrency, regular expressions, and the platform environment
06:54
java.sql は全部 SQLException なのはヤバいけど、検査例外なこと自体はおかしくないんじゃないかなぁ。
Avatar
omochimetaru 21-Oct-19 06:55 AM
他はそうでもないと思うようになりました。
06:56
List.addから飛んでくるunmodifiableは?
Avatar
koher 21-Oct-19 06:56 AM
あと、 null-safety がなくて NullPointerException で台無しってのと、 try! がないってのはその通りで、そのあたりの相乗効果で使いづらい。
06:57
イミュータブル関連は、例外の使い方というより型ヒエラルキーの設計の問題かと。
Avatar
omochimetaru 21-Oct-19 06:59 AM
他になんかなかったっけなあ
07:02
まあでもutilとかだとそもそも論理的なエラーになりえる場面がそんなにないか。
07:05
class MyE extends Exception{}; class A<E extends Exception> { void f() throws E {} } public class Main { public static void main(String[] args) throws Exception { try { new A<MyE>().f(); } catch (MyE e) {} } }
07:05
たしかに書けますね
07:06
パラメータ型のthrowsはできるから、Never型があったらよかったなあ。 (edited)
Avatar
koher 21-Oct-19 07:11 AM
でもJavaはthrowsの後ろに複数の例外を書けるから、それを一つの型パラメータで表現するには、それがUnionで表されるようにならないといけないんよね。
Avatar
omochimetaru 21-Oct-19 07:11 AM
ん?どういうことですか?
Avatar
koher 21-Oct-19 07:11 AM
catchするのは(7か8から)Union的に書けるようになってる。
Avatar
omochimetaru 21-Oct-19 07:11 AM
一つの型パラメータで複数は表せなくてもよいのでは
Avatar
koher 21-Oct-19 07:11 AM
throws FooException, BarExceptionを
07:12
throws Eで実現できない。
Avatar
omochimetaru 21-Oct-19 07:12 AM
Result<Integer, FooException | BarException>こういうことがしたくなりうるという話?
Avatar
koher 21-Oct-19 07:12 AM
たとえば、FunctionにEとthrows付けても、Neverがあっても
Avatar
omochimetaru 21-Oct-19 07:12 AM
うーんまあそうなるのか、普段から複数例外を並べているなら
Avatar
koher 21-Oct-19 07:12 AM
すべてのthrowsを表現できない。
Avatar
omochimetaru 21-Oct-19 07:13 AM
非同期APIとかもそうしたくなるはずか。
Avatar
koher 21-Oct-19 07:13 AM
なので、mapとrethrowsとかもできない。
Avatar
omochimetaru 21-Oct-19 07:14 AM
じゃあそれもいりますね、もしくはパラメータ化したいときは1個だけで我慢
Avatar
koher 21-Oct-19 07:18 AM
複数書ける仕様も良くない気がしてて、そのせいで雑に上の階層に投げなおされたりする。まあ、それはtyped throwsがなあ今のSwiftも同じかな。
Avatar
omochimetaru 21-Oct-19 07:19 AM
そのせいで
そのせいなのかどうかは微妙な気がしますけどね
07:19
Eclipseの提示するAuto Fixが「throws Exceptionにまとめる」が1番だったら
07:19
みんなthrows Exceptionにまとめていたような気もするし。
Avatar
koher 21-Oct-19 07:40 AM
null safety、try!、検査例外だけcatch、検査例外のparseInt、単一throwsが実現された世界なら検査例外素晴らしいってなるかもしれないけど、そりゃイメージできないよね。それだけ距離があると。
Avatar
omochimetaru 21-Oct-19 07:40 AM
まあそうですねw
07:40
Swiftコアチームはすごい。
Avatar
koher 21-Oct-19 07:40 AM
ほんとに。
Avatar
omochimetaru 21-Oct-19 07:41 AM
ある程度使ってやっと納得できた
Avatar
koher 21-Oct-19 09:16 AM
結果的に多くの言語が非検査例外に傾いちゃったのが残念だね。特にKotlinはきついなー。必要なものはほとんど揃ってそうなのに。
Avatar
Kishikawa Katsumi 21-Oct-19 10:09 AM
Javaのthrowsは全部列挙しなきゃいけなかったんだっけ。それは大変だな。だいぶ忘れてる。。。
Avatar
ヴァルボーグ@toyosuke 21-Oct-19 10:12 AM
IDE任せにしてたけどJavaは確かにそうなんだよな… 3つくらいのExceptionを関連メソッドに実装していった覚えがある
Avatar
koher 21-Oct-19 10:14 AM
SwiftはTyped Throwsが導入されてもthrowsに書けるのは一つのエラー型だけってChris LattnerかJoe Groffあたりが言ってたはず。
Avatar
omochimetaru 21-Oct-19 10:14 AM
それは言語がenumを持ってるから簡単にユニオン的な事ができるからってのもあるでしょうね
10:15
ユニオンよりもタグが付けられるから、同じエラー型でも複数経路ある場合区別できるし。
Avatar
koher 21-Oct-19 10:16 AM
そうすると下層のエラーが複数種類ある場合に雑にそのまま投げなおすことができないから、Errorとしてまとめるか、そのAPIに適したエラーに包みなおして適切な粒度でcaseを分けることになる。
10:16
Javaにtagged unionがないのもきついよね。
10:17
まあ、untagged unionがあればある程度なんとかなるのかな?
Avatar
omochimetaru 21-Oct-19 10:17 AM
throws句はuntagged unionを毎回書き下してるとも言えますね
10:18
typealiasでそのペアに名前が与えられたらまだ良かったかも。
Avatar
omochimetaru 21-Oct-19 10:36 AM
#swift ユーザーにアンケート 言語機能の検査例外(do,try,throw,throws)は
10:36
↑思ったよりは嫌い票が多い。
Avatar
koher 21-Oct-19 11:27 AM
throws句はuntagged unionを毎回書き下してるとも言えますね
うん。なので、先の型パラの話は、untagged unionがあれば解決するんよね。 throws A, B, Cをthrows A|B|Cのシュガーにする。
Avatar
omochimetaru 21-Oct-19 11:28 AM
untagged unionの直接記法がある状況と
11:28
それのtypealiasが命名できる状況にはもう一手、使い心地の違いがあると思って。
11:28
Javaにはtypealias無いですよね。
Avatar
koher 21-Oct-19 11:29 AM
catchについては、今のJavaでも
catch(A|B|C e) {
ができる。
11:30
typealiasはないね。 (edited)
Avatar
omochimetaru 21-Oct-19 11:30 AM
そこでtypealiasがないと、
11:30
カプセル化できてないから微妙な気がします
Avatar
koher 21-Oct-19 11:30 AM
typealiasはカプセル化はしなくない?
Avatar
omochimetaru 21-Oct-19 11:31 AM
例えば
11:31
class A { typealias Error = NumberFormatException | IOException; void f() throws Error { } }
11:31
こういう状況で、f()を呼び出して、そのままthrowsする関数をAのユーザーが作ったときに
11:31
A.Errorで再throwsを書ければ
11:32
将来A.Errorの右辺が変更したときも
11:32
「Aのエラーをそのまま再throws」っていう意味の記述が維持できるけど
11:32
typealiasが無いと、再throwsする関数のシグネチャも直さないといけない
11:33
そういう意味でAのユーザーにとってA.Errorの実体を無視することを許すのでカプセル化?かなと
Avatar
koher 21-Oct-19 11:33 AM
エイリアスの指すものは隠蔽されないし、rethrowで足りないものはコンパイルエラーで浮かび上がるから良いのでは?
Avatar
omochimetaru 21-Oct-19 11:34 AM
安全性は壊れないけど書き直すのは面倒じゃないですか。
Avatar
koher 21-Oct-19 11:34 AM
SwiftでErrorのenumでcaseを足したときと同じじゃないかなぁ。
11:34
違うか
Avatar
omochimetaru 21-Oct-19 11:34 AM
SwiftのErrorでcaseを足したときも、
11:34
そのまま投げる場合はそのままでいいですよね。
11:35
switchしてるところは追記しないといけないだけで。
Avatar
koher 21-Oct-19 11:35 AM
catch側だけ分岐しなおせばいいか。
Avatar
omochimetaru 21-Oct-19 11:35 AM
はい
Avatar
koher 21-Oct-19 11:35 AM
まあ、ただ、そのままrethrow自体が良いことじゃないから
11:35
そのための機能をサポートするのは微妙な気がする。
Avatar
omochimetaru 21-Oct-19 11:36 AM
引数のオーバーロードをちょっと足すだけみたいな状況なら
11:36
そのままrethrowするのが正しいコードだと思います
Avatar
koher 21-Oct-19 11:37 AM
オーバーロードでrethrowってどういうケース? Swiftでrethrows使ってるようなケースはまさにrethrowが良いと思うけど。
11:38
それはでも型パラがエイリアス代わりになる。
Avatar
omochimetaru 21-Oct-19 11:40 AM
ライブラリにA.f(float x) throws Error みたいな関数があったときに、 アプリモジュールで追加してる Angleみたいな型があったとして、a.f(angle)ってそのまま渡せるように A.f(Angle angle) throws Error を追加するみたいなケース。 実装としては、angle.valueを元のfに転送するだけ。
Avatar
koher 21-Oct-19 11:56 AM
そういうケースは素通しさせたいかもだけど、それって戻り値も同じ話にならない?throwされるエラー値って戻り値の一種だし。Resultで考えてみたらエラー型だけ素通ししたいってのは変な要求では? (edited)
Avatar
omochimetaru 21-Oct-19 11:58 AM
同様に、戻り値にunion typeを使うなら、将来増えそうなのでtypealiasしておいてほしいですね
11:58
Swiftでenumを使うときに
11:58
返り値の型のところで毎回caseを書き並べていたら不便でしょう。
Avatar
koher 21-Oct-19 12:03 PM
うーん、unionの要素(?)が増えるってpublicなAPIの変更なわけで、unionの変更に限らず戻り値の型の変更とかと同じで、それなりに大ごとだしコンパイラが検出できるならいいんじゃないかな?typealiasが助けになる面はあるとしても、あまり本質的なことじゃない気が。 (edited)
Avatar
omochimetaru 21-Oct-19 12:04 PM
Swiftでenumのcaseが増えるときは、その値をswitchで開いて使うところでしか変更が生じないのと同じじゃないですか?
12:05
enumの型名を変数名、引数、返り値の型に使ってるところは、そのままです。
12:05
caseが増えたときに、そうした箇所全てを直すのは、大変すぎるし特に意味がないと思う。
12:07
なので、untagged union typeが導入される場合、そのunionの組に対して名前をつける機能はセットじゃないと
12:07
つかいづらいとおもう
Avatar
koher 21-Oct-19 12:22 PM
でもそれって、untagged unionを使うAPIの設計者がtypealiasを付けてくれないとダメじゃない?それを強制したいならtagged unionが必要なのでは?
Avatar
omochimetaru 21-Oct-19 12:23 PM
付けれたら付けてくれると思います 強制はできないですね Swiftでもラベル付きタプルを返り値の型に直接書くか、typealiasしておくか、みたいな時は似たような状況になる。
Avatar
koher 21-Oct-19 02:31 PM
タプルにエイリアスみたいなときはたいていstructが正解じゃないかなぁ。
Avatar
omochimetaru 21-Oct-19 02:32 PM
同じ話だと思います。
14:32
タプルはフィールドの積で、untagged unionはフィールドの和だから。
Avatar
koher 21-Oct-19 02:33 PM
うん。non-nominalのエイリアスって微妙なケースが多くて、それだったらnominalにした方が良いという感覚だから、untagged unionにエイリアスってピンと来なくて、それはtagged unionが必要なんじゃないかと。 (edited)
Avatar
omochimetaru 21-Oct-19 02:34 PM
むむ、それは論点がずれてると思います
14:34
untagged unionかtagged unionかの違いは
14:34
データ構造として、unionでマージしてる個別の要素を、型だけで区別するか、名前をつけて区別するかであって
14:34
そのまとめた全体に名前をつけられるかどうか、は直交する話だと思います。
14:34
つまり・・・
14:37
untagged union: (FileIOError | NetworkError) ↓名前を付けたuntagged union DownloadError = (FileIOError | NetworkError) tagged union: (cacheFileIOError: FileIOError | downloadFileIOError: FileIOError | network: NetworkError) ↑taggedは、ケースにtagがついているので、FileIOErrorを2つ区別して保持できる tagged unionに名前が付けられる: ↓これの左辺の事 DownloadError = (cacheFileIOError: FileIOError | downloadFileIOError: FileIOError | network: NetworkError) (edited)
14:37
Swiftのenumに関して言えば、
enum DownloadError // ←ここに名前がつくかどうかじゃなくて { case cacheFile(FileIOError) // ←このケースと case downloadFileIOError(FileIOError) // このケースが区別できるのがtag case network(NetworkError) }
(edited)
14:38
で、Swiftのタプルは、taggedな値の積なんじゃないかなと
14:43
実際他の言語の例だとTypeScriptは名前が付けられるuntagged unionです https://github.com/ReactiveX/rxjs/blob/5.5.12/src/Observable.ts#L19 (edited)
A reactive programming library for JavaScript. Contribute to ReactiveX/rxjs development by creating an account on GitHub.
14:44
(最新のmasterでその部分の設計が変わっていたので5系のリンクですが・・・) (edited)
14:45
A reactive programming library for JavaScript. Contribute to ReactiveX/rxjs development by creating an account on GitHub.
Avatar
koher 21-Oct-19 03:09 PM
そのまとめた全体に名前をつけられるかどうか、は直交する話だと思います。
たしかにそれはそうだなぁ。
15:13
そうすると論点は↓で
caseが増えたときに、そうした箇所全てを直すのは、大変すぎるし特に意味がないと思う。
これはたまたまenumではそうだけど、戻り値の型が変わったら素通しで投げ返してる箇所全部変更するわけだし、エイリアスで解決できるのは一部のケースだけだし、その一部がエイリアスを導入することを正当化できるのかかなぁ。
15:14
現にJavaのthrowsはすでに同じ問題を抱えてるはずだけど、エイリアスなしでやってきてるわけだし。
15:15
エイリアスは役に立つかもしれないけど、それは複数例外のthrowsをunionで書けるようにする話とは独立なんじゃないかな?
Avatar
omochimetaru 21-Oct-19 03:15 PM
そこもまた別ですね。
Avatar
koher 21-Oct-19 03:16 PM
関係ないけど、たまたま今Java界隈が検査例外で盛り上がってるみたいだね。
Avatar
omochimetaru 21-Oct-19 03:16 PM
現にJavaのthrowsはすでに同じ問題を抱えてるはずだけど、エイリアスなしでやってきてるわけだし。
ここがやってこれなかった理由じゃないかなあと思っていて、ここまでの僕の意見の流れがあります。
15:16
根っこで1種類増えると素通し系全部throwsのところ直さなきゃいけなくて、やってられ〜んと思って、後続の言語がやめちゃった。
15:17
ですね、朝なぎせさんがツイートしてた
15:17
チェック例外の議論してるのに、パッと見、Swiftの言及がないのはなんなんだぜ? https://t.co/aiYxUmBzPt
Avatar
koher 21-Oct-19 03:18 PM
↓これどういうケースだろ? https://twitter.com/gakuzzzz/status/1185168047838879744?s=21
ただ、やっぱりEitherと比較すると関数合成で特定のパターン(f . g で fがエラーを返しgがエラーをリカバリーするようなパターン)を実現できないので、柔軟性という意味ではEitherの方がまだ利がありそう...
15:19
あ、前のツイートからの続きでSwiftのtyped throwsの話してる。
Avatar
omochimetaru 21-Oct-19 03:20 PM
がくぞさんにもrethrowsの仕様伝わってるのか、良かった
Avatar
koher 21-Oct-19 03:21 PM
ここがやってこれなかった理由じゃないかなあと思っていて、ここまでの僕の意見の流れがあります。
なるほどー。それなら筋の通る話ではあるね。ただ、本来素通しはそんなに起こらないと思ってて、苦しんでるほとんどのケースは雑な素通しが原因だと思うんよね。
Avatar
omochimetaru 21-Oct-19 03:24 PM
がくぞさんの言ってるのは、 g() -> Either<A, E> と f() -> Either<A, E> に対して、 gとfを合成して述べてるような関数を作る高階関数hを構成できることを言ってるのかな?
Avatar
koher 21-Oct-19 03:25 PM
違うか。包み直すのが理想的なのはそうとして、実際問題ほとんどはエラーかどうかがわかればいいから、現実的に雑な素通しが横行することになって、そこでthrows Exceptionができればよかったんだけど、RuntimeException巻き込み問題があるからそれもできないと。
Avatar
omochimetaru 21-Oct-19 03:25 PM
本来素通しはそんなに起こらないと思ってて、苦しんでるほとんどのケースは雑な素通しが原因
そこはやってみたことがないからなんとも言えないんですけど、雑な素通しで良いケースが結構多い気はしている
15:26
あ、そうですね、Javaの場合はそこでRE巻き込み問題が絡んでくる。
15:26
Combineにはエラーの型がついたから、試しに取り組むならCombine上でちゃんとやるのがいいでしょうね (edited)
Avatar
koher 21-Oct-19 03:26 PM
なんか細かいやらかしがたくさん積み重なりすぎて詰んでるよね😅
Avatar
omochimetaru 21-Oct-19 03:27 PM
いなみさんとかはReactiveSwiftでエラーの型ちゃんと合成してんのかな〜
Avatar
koher 21-Oct-19 03:27 PM
Swiftに最初からtyped throws入れなかったの、Core Team賢すぎるな。
Avatar
omochimetaru 21-Oct-19 03:28 PM
まあJavaはそうですね>積み重なり
15:28
Kotlinが刷新してくれたらよかったがそうはならなかったので
15:28
次のAltJavaに期待
Avatar
koher 21-Oct-19 03:28 PM
Kotlinに検査例外ないのほんと辛いよね。
Avatar
omochimetaru 21-Oct-19 03:29 PM
まあinline funからのreturnができるんで、Eitherで頑張る手もある
Avatar
koher 21-Oct-19 03:29 PM
null safeだけとerror unsafeになっちゃったという…。
Avatar
omochimetaru 21-Oct-19 03:30 PM
あーでもそれだと自分でtryの振る舞いを書き下してるだけか
Avatar
koher 21-Oct-19 03:31 PM
今さらKotlinとScalaを超えるAltJavaが出てきて覇権をとるイメージがわかないなぁ。10年は無理では。
Avatar
omochimetaru 21-Oct-19 03:31 PM
do記法のあるscalaはその点は結構いいですね
15:31
scala3は結構期待できるのかも
15:31
最近仕様?が出始めたらしくて、結構変わっている
15:31
らしい
Avatar
koher 21-Oct-19 03:36 PM
scalaのdo記法ってforのこと?
Avatar
omochimetaru 21-Oct-19 03:36 PM
あ、forでした
15:37
でもあれはifとかとシームレスではないか。
Avatar
koher 21-Oct-19 03:37 PM
throws/tryやasync/awaitのいいところって、制御構文と柔軟に組み合わせられるとこだと思うけど
15:38
って同じことを言おうとしてるかな?
Avatar
omochimetaru 21-Oct-19 03:38 PM
あ、はい
15:39
その絡みでいうと
15:39
『0から知った気になるAlgebraic Effects』で発表しました。 ご清聴ありがとうございました。 スライドはこちらです。 https://t.co/1qC5hONvLS #FunFunFunctional
Avatar
koher 21-Oct-19 03:39 PM
モナド、そのあたりが辛いけど、Haskellとかうまくやれんのかな?パズルになりそうな印象なんだけど。
Avatar
omochimetaru 21-Oct-19 03:39 PM
↑この資料と出会って、ついにEff読めるようになりました
Avatar
koher 21-Oct-19 03:40 PM
おお
15:40
これでJoe Groffの言ってることがわかる?
Avatar
omochimetaru 21-Oct-19 03:40 PM
わかった
Avatar
koher 21-Oct-19 03:42 PM
見てみよう
Avatar
omochimetaru 21-Oct-19 03:42 PM
I've thought about this some. It might not have to be a keyword, if this were a generalized language feature. Anything that interrupts control flow and optionally resumes it later, such as 'throws', 'yields', and potentially also 'async', could be implemented as instances of ...
15:43
これは要するにEffのAlgebraic effectsをSwiftな構文で組み込むならこんな感じにできそーって話
👍 1
15:44
読んでみてください
Avatar
t.ae 25-Oct-19 02:54 AM
Swift5.1 on UbuntuでDateComponents.dateがmacと比べてめちゃくちゃ遅いっぽい…… ubuntuはDocker上でしかためしてないんでオーバーヘッドはあると思いますが流石にこの差はなにかありますよね? mac:
$ cat main.swift import Foundation var comps = DateComponents( calendar: Calendar(identifier: .gregorian), timeZone: TimeZone(secondsFromGMT: 0)! ) comps.year = 2019 comps.month = 11 comps.day = 10 comps.hour = 10 comps.minute = 10 comps.second = 10 comps.nanosecond = 10 let start = Date() var total: TimeInterval = 0 for _ in 0..<10_000 { total += comps.date?.timeIntervalSinceNow ?? 0 } print("time: \(Date().timeIntervalSince(start))sec, \(total)") $ swiftc -O main.swift $ ./main time: 0.011227965354919434sec, 14087090925.878277
ubuntu on dokcer on mac:
root@15ebe51be255:/var/vapor-app# swiftc -O main.swift root@15ebe51be255:/var/vapor-app# ./main time: 1.0126609802246094sec, 14088576437.363556
02:55
VaporのMySQLからDateデコード処理がこれで、しかも関連する型がinternalなので自前実装に変えるのが面倒そう (edited)
Avatar
omochimetaru 25-Oct-19 02:56 AM
100倍は遅すぎるとは思うけど流石にdocker on macは仮想環境なのでそこは実Linuxで見ないとなんとも。
Avatar
t.ae 25-Oct-19 02:56 AM
スペック違うので単純比較できないですけどとりあえずやってみます。 (edited)
Avatar
omochimetaru 25-Oct-19 02:58 AM
(まあクラウドも仮想環境ですけど
Avatar
t.ae 25-Oct-19 02:58 AM
(現在クラウドにデプロイを試みているという文脈
Avatar
Kishikawa Katsumi 25-Oct-19 03:00 AM
Swiftbotでやってみたけど同じくらいですねえ。あれもDockerだけど。
Avatar
t.ae 25-Oct-19 03:11 AM
Azure VM B2Sインスタンスにて
$ swiftc -O main.swift $ ./main time: 0.4973900318145752sec, 14075794190.737843
03:15
クラウドはCPU性能がよく分からないので比較には向いてなさそうですね…… 自宅のubuntuマシンで確認して三環境分まとめてbugsに報告が良いか。
Avatar
hironytic 25-Oct-19 03:24 AM
最終的にはICUに渡して日付計算を行なっているみたいで、そのために(?)いろいろ変換とかしてるようなので、その分時間がかかっているのかも、しれない、と思いました。
03:24
The Foundation Project, providing core utilities, internationalization, and OS independence - apple/swift-corelibs-foundation
Avatar
norio_nomura 25-Oct-19 03:30 AM
4.x -> 5.xで2倍くらい遅くなってるぽい。
$ pbpaste|docker-swift41 -O - time: 0.272868990898132sec, 14066769520.098 $ pbpaste|docker-swift42 -O - time: 0.32283997535705566sec, 14066729445.257643 $ pbpaste|docker-swift50 -O - time: 0.5901000499725342sec, 14066676853.962284 $ pbpaste|docker-swift51 -O - time: 0.5475540161132812sec, 14066619176.887285 $ pbpaste|docker-swiftnightly -O - time: 0.779636025428772sec, 14066542714.192633 $ pbpaste|swift42 -O - time: 0.013067960739135742sec, 14066457781.279984 $ pbpaste|swift50 -O - time: 0.01632702350616455sec, 14066407578.90026 $ pbpaste|swift51 -O - time: 0.014343976974487305sec, 14066365250.005945
(edited)
Avatar
t.ae 25-Oct-19 03:31 AM
文字列に変換してDateFormatterで変換したほうが3倍くらい速い
# cat main2.swift import Foundation let df = DateFormatter() df.dateFormat = "yyyy/MM/dd HH:mm:ss.SSSSSSS" let start = Date() var total: TimeInterval = 0 for _ in 0..<10_000 { let year = 2019 let month = 11 let day = 10 let hour = 10 let minute = 10 let second = 10 let microsecond = 101010 let date = df.date(from: "\(year)/\(month)/\(day) \(hour):\(minute):\(second).\(microsecond)") total += date?.timeIntervalSinceNow ?? 0 } print("time: \(Date().timeIntervalSince(start))sec, \(total)")root@15ebe51be255:/var/vapor-app# swiftc -O main2.swift root@15ebe51be255:/var/vapor-app# ./main2 time: 0.32200801372528076sec, 14063930163.143023
😅 1
03:32
5系でなにか変更あったんですかね。
Avatar
norio_nomura 25-Oct-19 03:43 AM
icuがtoolchainに同梱される様になったのが5.0からじゃなかったかな?
Avatar
omochimetaru 25-Oct-19 03:43 AM
文字列経由の方が早いのは笑うw
03:44
パースが要らない分compsのほうが早いはずなのに、、
Avatar
hironytic 25-Oct-19 03:47 AM
さっきの変換自体は昔からあるみたいなので関係なさそう。
Avatar
t.ae 25-Oct-19 03:48 AM
昔の段階でmacOS上と比べて遅いかどうかは依然気になるところではありますね。
Avatar
hironytic 25-Oct-19 03:49 AM
そうか。昔もmacOSに比べると遅かった可能性は十分ありますね。
Avatar
norio_nomura 25-Oct-19 03:51 AM
4.2でも遅い。
$ pbpaste|docker-swift42 -O - time: 0.27475202083587646sec, 14051535205.538399 $ pbpaste|swift42 -O - time: 0.012828946113586426sec, 14051471374.175034
Avatar
t.ae 25-Oct-19 03:51 AM
ああ、これdocker-ついてない方はmacなんですかね。 (edited)
Avatar
norio_nomura 25-Oct-19 03:52 AM
そそ。
Avatar
hironytic 25-Oct-19 03:52 AM
Swift 5というと、このへんで大きく変わってはいるみたい。大きく変わりすぎててコードの変化がよくわからない。 https://github.com/apple/swift-corelibs-foundation/pull/1755
In the Mojave timeframe, we have extensively overhauled the way CFCalendar (and consequently, NSCalendar and struct Calendar) work, and improved accuracy, stability and test coverage of several cla...
03:53
CFCalendar.cの _CFCalendarComposeAbsoluteTimeV がICUを呼び出しているところだと思うんですが、 そこが大きく変わっているような (edited)
03:58
いや、そんなに大きくは変わってないみたいでした
Avatar
t.ae 25-Oct-19 04:03 AM
DateFormatterと速度逆転する時点でおかしいしこれだけ提示して報告で良さそうですね。
Avatar
t.ae 25-Oct-19 04:26 AM
https://bugs.swift.org/browse/SR-11667 投稿しました。何か追記することがあったら書いてください。
Avatar
norio_nomura 25-Oct-19 04:30 AM
DateFormatter使った方はmacOSとそんなに変わらないのね。
Avatar
t.ae 25-Oct-19 04:32 AM
macのCPUが2.7GHzでubuntuのが2.3GHzなのでその差って感じですね。 (edited)
Avatar
norio_nomura 25-Oct-19 04:38 AM
ぬ、CPU specに差があるなら それを一応書いておくべきでは。
Avatar
t.ae 25-Oct-19 04:39 AM
単純にDateFormatterと比較して遅いのはおかしい。ってつもりでしたが書いておきますね。
Avatar
norio_nomura 25-Oct-19 12:05 PM
perfでprofileしてみた。
Avatar
omochimetaru 02-Nov-19 02:31 AM
コンパイラのバグとして報告されてる。めっちゃシンプルで草。ひどい。 https://t.co/hmXoZqBdok
02:33
Swiftコンパイラ史のなかでもトップのヤラカシだと思った アプリのRxSwiftで踏んで様子見てたんですけど、もっと条件ゆるかった
Avatar
koher 02-Nov-19 11:36 AM
We found a workaround. Setting DEAD_CODE_STRIPPING = NO in our app’s target fixes the crash.
(edited)
Avatar
omochimetaru 02-Nov-19 11:38 AM
Short description of the issue: I&#39;m getting crashes when using merge() with Xcode 11.2. Same code with 11.1 works fine. What actually happens: EXC_BAD_ACCESS (code=1, address=0x0) frame #0:...
11:38
こっちのスレだとそれでも直らない人も居るみたい
😢 2
11:39
DCE(Dead code elimination)無効化で直るのは
11:39
条件の組み合わせ的な話でroot issueではないんじゃないかなという気がする
11:39
条件にSwiftPMによるビルドっていうのがあるので
11:39
メタデータシンボルの可視性とかリンク時の解決が
11:40
微妙にSwiftPMが組むビルドによって異なっているとかじゃなかろうか
Avatar
omochimetaru 05-Nov-19 07:05 PM
This review ended on October 21st, but because of the LLVM conference, the Core Team didn't have an opportunity to discuss it until last week. Swift's indexing model is based on solid concepts that have held up well over the years, but the verbosity of expressing positions a...
19:06
新しいオフセットインデックス記法のレビューが改善してやり直しになった
19:07
もし必要ならスライスのためにコア言語機能の拡張もありうる、とかも書いてある
Avatar
koher 06-Nov-19 07:10 AM
これ通ったらちゃんと読もうと思ってたけどやり直しになったのか。
Avatar
omochimetaru 06-Nov-19 08:00 AM
MichaelさんSwiftチーム入ってずっとStringAPIについて考えてるのに
08:00
正規レビューの段階でコアチームからこのツッコミ入って差し戻しされるの
08:00
ちょっとかわいそうだなって思った・・・
Avatar
rintaro 07-Nov-19 10:09 PM
I’m excited to announce a new open-source project for the Swift ecosystem, Swift Numerics! Swift Numerics will provide the building blocks of numerical computing in Swift, as a set of fine-grained modules bundled together into a single Swift package. My hope is that we can ...
Avatar
omochimetaru 08-Nov-19 01:10 AM
おお!?
Avatar
tarunon 08-Nov-19 01:12 AM
numpyのswift版ですか?
Avatar
omochimetaru 08-Nov-19 01:12 AM
いや
Avatar
t.ae 08-Nov-19 01:12 AM
内容的にはまだComplexとRealしか無いのでそこまではいってなさそう
Avatar
omochimetaru 08-Nov-19 01:13 AM
実数プロトコルと複素数だね
Avatar
tarunon 08-Nov-19 01:13 AM
ふむ
Avatar
omochimetaru 08-Nov-19 01:14 AM
続きでやりたいって言ってるShapedArrayが任意階数のテンサー?
Avatar
tarunon 08-Nov-19 01:15 AM
あ、ShapedArrayはまだ実在しないのか
Avatar
omochimetaru 08-Nov-19 01:17 AM
A ShapedArray protocol and supporting types, capable of representing multidimensional homogeneous data. If you’ve worked with S4TF before, you’re already familiar with this concept; otherwise, you may have used NumPy arrays in Python, or Fortran, Matlab or Julia arrays.
01:18
これがあるとないとじゃ全然別の粒度のライブラリに見えそうだな オペレータの数もめちゃくちゃ増えるだろうし
Avatar
koher 08-Nov-19 06:57 AM
https://github.com/apple/swift-numerics/blob/master/Package.swift
targets: [ .target(name: "Complex", dependencies: ["Real"]), .target(name: "Numerics", dependencies: ["Complex", "Real"]), .target(name: "NumericsShims", dependencies: []), .target(name: "Real", dependencies: ["NumericsShims"]), ... ]
Numerical APIs for Swift. Contribute to apple/swift-numerics development by creating an account on GitHub.
Avatar
crcrpar 08-Nov-19 07:04 AM
これsqrtでintermediate overflow/underflowがないと書いてあるように読めるのですが、どう実現するんでしょう (edited)
Avatar
t.ae 08-Nov-19 07:07 AM
hypot自体がもともとoverflowしないようになってたような。
07:07
hypot, which computes sqrt(xx + yy) without intermediate overflow or underflow.
ここですよね?
Avatar
crcrpar 08-Nov-19 07:08 AM
そこです
Avatar
t.ae 08-Nov-19 07:09 AM
Hypot is a mathematical function defined to calculate the length of the hypotenuse of a right-angle triangle. It was designed to avoid errors arising due to limited-precision calculations performed on computers.
Avatar
koher 08-Nov-19 07:10 AM
sqrt の前に x * x とかでオーバーフローしないって意味ですよね?
07:11
シンプルに sqrt(x*x + y*y) として実装するとオーバーフローしちゃうかもしれないから (edited)
Avatar
omochimetaru 08-Nov-19 07:12 AM
Numerical APIs for Swift. Contribute to apple/swift-numerics development by creating an account on GitHub.
07:13
libmのhypotの実装に依存してそう
Avatar
crcrpar 08-Nov-19 07:14 AM
このあたり意識したことないのですが、このdocs見る限りオーバーフローは起きることもあるのでは、、、と思いました(こなみ) http://www.cplusplus.com/reference/cmath/hypot/
Avatar
t.ae 08-Nov-19 07:15 AM
最終結果のoverflowと計算途中のoverflowは別で、計算途中のほうだけ(xx + yyによるところだけ)起こらないんじゃないでしょうか。
07:16
https://cpprefjp.github.io/reference/cmath/hypot.html
算術型の平方和の平方根を求める。この際、余計なオーバーフロー、アンダーフローを起こさない。
>オーバーフローエラー、アンダーフローエラーが発生する可能性がある。
算術型の平方和の平方根を求める。この際、余計なオーバーフロー、アンダーフローを起こさない。hypot は hypotenuse((直角三角形の)斜辺)の略。
Avatar
omochimetaru 08-Nov-19 07:17 AM
概要の「余計なオーバーフロー、アンダーフローを起こさない」とは、たとえ x2 が戻り値型の範囲を超えていても、結果が戻り値型の範囲に収まるのであればオーバーフローしないで正しい結果を返す、と言う事である。
Avatar
koher 08-Nov-19 07:17 AM
Finally, the multiplication by |x| cannot underflow, and overflows only when the result is too large to represent.
Avatar
t.ae 08-Nov-19 07:17 AM
そこを引くべきだった
Avatar
koher 08-Nov-19 07:17 AM
さっきの @t.ae の Wikipwdia にも書いてあった。
Avatar
t.ae 08-Nov-19 07:18 AM
例えばhypot(Float.max, 0)はオーバーフローしないけどhypot(Float.max, 100)とかはするってことですね。 (edited)
Avatar
koher 08-Nov-19 07:18 AM
float function hypot(float a, float b) { let [float x, float y] = [ // x ≥ y max(abs(a), abs(b)), min(abs(a), abs(b)) ]; if (x == 0) // x = y = 0 return 0; // avoid division by zero let float t = y / x; // 0 < t ≤ 1 return x * sqrt(1 + t * t); // > 0 }
Avatar
omochimetaru 08-Nov-19 07:19 AM
あ〜
07:20
sqrt ( x^x + y^y ) == x * sqrt ( (x^x + y^y) / x^2 ) == x * sqrt ( 1 + (y/x)^2 )
07:20
こういうこと?
07:22
実装が見たいけど__builtin_hypotとやらになっててその先がわからん、これどこから来るんだ
Avatar
koher 08-Nov-19 07:25 AM
GitHub is where people build software. More than 40 million people use GitHub to discover, fork, and contribute to over 100 million projects.
07:27
These functions provide compatibility with GNU library header files. The functions are described in the GNU documentation.
Avatar
omochimetaru 08-Nov-19 07:29 AM
これも計算の実態は書かれてない
Avatar
crcrpar 08-Nov-19 07:32 AM
I have a MIPS program to compute the hypotenuse from two integers. However the program prints some weird number not the actual result, my best guess is there is something wrong with the square root
Avatar
koher 08-Nov-19 07:56 AM
↓やって遊ぼうとしたけど、 Complexsqrt がなさそう🙁
import Numerics let a: Complex<Double> = -1 let i: Complex<Double> = .sqrt(a) print(i)
(edited)
Avatar
koher 08-Nov-19 08:12 AM
↓で遊べたけど誤差が・・・
import Numerics extension Complex { static func *(lhs: Self, rhs: RealType) -> Self { return Self(lhs.real * rhs, lhs.imaginary * rhs) } static func *(lhs: RealType, rhs: Self) -> Self { return Self(lhs * rhs.real, lhs * rhs.imaginary) } } extension Complex where RealType: ElementaryFunctions { static func sqrt(_ z: Self) -> Self { let length = z.length let phase = z.phase return .sqrt(length) * Self(.cos(phase / 2), .sin(phase / 2)) } } let a: Complex<Double> = -1 let i: Complex<Double> = .sqrt(a) print(i)
(6.123233995736766e-17, 1.0)
08:17
お、すでに提案されてる。 https://github.com/apple/swift-numerics/issues/2
All of the usual ElementaryFunctions operations should be defined for Complex types. Implementation details may be found in Kahan&#39;s &quot;Branch Cuts for Complex Elementary Functions; o...
08:19
というか、初期の実装から外しただけか。
Avatar
t.ae 08-Nov-19 11:51 AM
Complex使ってるライブラリを置き換えようかと思ったんですがまだタグ一個も切られてないんですね。時期尚早か。
Avatar
t.ae 08-Nov-19 05:05 PM
https://github.com/apple/swift-numerics/blob/master/Sources/Complex/Arithmetic.swift ComplexSignedNumericじゃないんですね。 https://developer.apple.com/documentation/swift/signednumeric
The SignedNumeric protocol extends the operations defined by the Numeric protocol to include a value’s additive inverse.
定義的には適合しそうですがどうなんでしょう。
Numerical APIs for Swift. Contribute to apple/swift-numerics development by creating an account on GitHub.
Avatar
t.ae 09-Nov-19 02:26 AM
https://developer.apple.com/documentation/swift/signednumeric The SignedNumeric protocol extends the operations defined by the Numeric protocol to include a value’s additive inverse. AFAICS Compl...
Avatar
omochimetaru 09-Nov-19 02:27 AM
無言だ・・・
Avatar
t.ae 13-Nov-19 12:10 AM
Hello Swift community, The review of SE-0271 “Package Manager Resources" begins now and runs through November 19, 2019. Reviews are an important part of the Swift evolution process. All reviews should be made in this thread on the Swift forums or, if you would like to kee...
00:11
やっと#fileから取るのから脱却できる
Avatar
omochimetaru 13-Nov-19 01:29 AM
おお!正規レビュー入ったか!
Avatar
nanasi 14-Nov-19 03:24 AM
Hello Swift community, The review of SE-0272 “Package Manager Binary Dependencies" begins now and runs through November 20, 2019. Reviews are an important part of the Swift evolution process. All reviews should be made in this thread on the Swift forums or, if you would l...
03:25
バイナリのほうも来ましたね
❤ 1
Avatar
omochimetaru 14-Nov-19 03:25 AM
おおっ、マジか! チェックしなきゃ!
Avatar
omochimetaru 14-Nov-19 04:15 AM
Software vendors who wish to provide easy integration with the package manager, but do not deliver source code, cannot integrate.
↑これはまあわかるし広告SDKに苦しむ各位が喜ぶと思うけど
04:16
Someone wants to create a Swift package for generating LLVM code. However, LLVM's build process is far more complex than can be currently fit into SwiftPM's build model. This makes building an easy to use package difficult.
04:16
↑この発想は無かった!w
Avatar
t.ae 18-Dec-19 02:04 AM
https://forums.swift.org/t/operator-member-syntax/31773/11 コンパイラ弱者なので分かってないのですがトップレベルのオペレータ関数とstaticなオペレータ関数でコンパイラ内部での扱いは違うんでしょうか? ユーザーが見る分には今の所同じですよね? (edited)
Good question. Operator member syntax is relevant only for operators declared as static methods of a particular type, not for operators declared as top-level functions. infix operator +++ // This operator is a top-level function, not a member of any type. func +++(_ x: Int,...
02:10
提案されている内容はstaticなオペレータ関数はその型のメンバーとしてアクセスできるようにするってことですが、現状定義を見ないとstaticなのかトップレベルなのか分からないのでユーザーからすると不便な気がしています。 (今の所定義によって挙動が変わらないので二種類の定義方法があってもユーザーに不便はない) (edited)
Avatar
omochimetaru 18-Dec-19 02:27 AM
知らんけど同じだと思ってる
02:28
別にこれは参照する方法を追加するだけで
02:28
今より不便になる点は無いのでは?
Avatar
t.ae 18-Dec-19 02:29 AM
追加的な機能なので不便にはならないですが、この機能を使う人からすると不便じゃないかと思ってます。
02:30
一般の関数の場合staticなのかトップレベルなのかはかんたんに見分けられますがオペレータ関数の場合定義もとに行かないと分からない
Avatar
omochimetaru 18-Dec-19 02:31 AM
一般の関数の場合見分けられるのは、返り値の型でわかるから?
Avatar
t.ae 18-Dec-19 02:31 AM
staticの場合外部からの呼び出しでは型名が要求されるからですね
Avatar
omochimetaru 18-Dec-19 02:32 AM
型名がない場合同士で比較しないと話が変では
Avatar
t.ae 18-Dec-19 02:32 AM
static関数からstatic関数を参照する場合は一応ありますね。 (edited)
Avatar
omochimetaru 18-Dec-19 02:32 AM
いや
02:32
ドット記法
Avatar
t.ae 18-Dec-19 02:32 AM
あ、あー
02:32
それは確かに
Avatar
omochimetaru 18-Dec-19 02:33 AM
SwiftPMとかだと使いまくるし普段も.some書くでしょ
02:33
あれと同じ話だと思う。
02:34
ドット記法は返り値の型が定義してる型同じ時だけ使えるけど
02:34
もし複数の型に同じstatic funcがあるときは
02:34
ドット記法だったら推論次第で呼び出しが変わるから
02:34
オペレーターと同じだと思う
02:35
オペレーターは名前が被りまくってるからわかりにくくなりやすいけど、 同じ分かり難さはすでにstatic funcにもある。
Avatar
t.ae 18-Dec-19 02:37 AM
@swiftbot
func f(_ x: X) -> X { print("top-level") return x } struct X { static func f(_ x: X) -> X { print("static") return x } } let x = X() let _: X = .f(x) // static
🛠 1
Avatar
swiftbot BOT 18-Dec-19 02:37 AM
Author icon
t.ae
func f(_ x: X) -> X { print("top-level") return x } struct X { static func f(_ x: X) -> X { print("static") return x } } let x = X() let _: X = .f(x) // static
Version:
swift-5.1-RELEASE
Output:
static
Error:
Avatar
t.ae 18-Dec-19 02:37 AM
@swiftbot
func f(_ x: X) -> X { print("top-level") return x } struct X { // static func f(_ x: X) -> X { // print("static") // return x // } } let x = X() let _: X = .f(x)
🛠 1
Avatar
swiftbot BOT 18-Dec-19 02:37 AM
Author icon
t.ae
func f(_ x: X) -> X { print("top-level") return x } struct X { // static func f(_ x: X) -> X { // print("static") // return x // } } let x = X() let _: X = .f(x)
Version:
swift-5.1-RELEASE
Output:
Error:
/usercode/main.swift:14:13: error: type 'X' has no member 'f' let _: X = .f(x) ~^~~~
Avatar
t.ae 18-Dec-19 02:42 AM
>ドット記法だったら推論次第で呼び出しが変わるからオペレーターと同じだと思う ドット記法って左辺型のstaticメンバが呼び出される仕様じゃなかったですっけ?
02:42
@swiftbot
struct X {} struct Y { static func f(_ x: X) -> X { print("Y") return x } } let x = X() let _: X = .f(x)
🛠 1
Avatar
swiftbot BOT 18-Dec-19 02:42 AM
Author icon
t.ae
struct X {} struct Y { static func f(_ x: X) -> X { print("Y") return x } } let x = X() let _: X = .f(x)
Version:
swift-5.1-RELEASE
Output:
Error:
/usercode/main.swift:11:13: error: type 'X' has no member 'f' let _: X = .f(x) ~^~~~
Avatar
t.ae 18-Dec-19 02:45 AM
ん、なんか文章読み間違ってますね。こんがらがってきた
Avatar
omochimetaru 18-Dec-19 02:50 AM
XとY の両方にstatic func fがあったら
02:50
.fって式が曖昧になることはある
02:51
で、それは、オペレーターが定義されてる型がわからないのと同じ。
Avatar
t.ae 18-Dec-19 02:51 AM
ありますか?_: X = .f(x)だったらXの方で解決されますよ
Avatar
omochimetaru 18-Dec-19 02:51 AM
例えば関数の引数だったら
02:51
見てもわからない
02:52
ん?解決できるかどうかじゃなくて
02:53
人間が見てもわかりにくいって話を
02:53
したいんだよね?
Avatar
t.ae 18-Dec-19 02:53 AM
そうですね。前提からこんがらがってきてます。
Avatar
t.ae 18-Dec-19 03:02 AM
static関数でドット記法の場合、受ける型さえわかればその場でどれを参照しているのかが分かる。 一方オペレータ関数の場合はそれがトップレベル/staticどちらで定義されているかのヒントは記述からは得られないため、定義元を見に行く必要がある。 というのが不便じゃないかというのが僕の言いたいことですね。
03:05
でこれは結局オペレータ関数の記法に2つのオプションがあること、かつ(知ってる限りでは)どちらを使うのが好ましいというような指針もないことが問題な気がしてきました。
Avatar
omochimetaru 18-Dec-19 03:10 AM
というのが不便じゃないか
これはすでにある性質であって、今回の提案とは関係ない話じゃ?
(edited)
03:11
今回の提案は、「わかってる場合に指定できる」というものであって。
03:11
現状では、わかってても指定できない。
Avatar
t.ae 18-Dec-19 03:29 AM
そうですね。分からない場合に定義を見に行く必要があると書きましたがその手間を経て分かっている場合に指定できるという点は良いと思います。
Avatar
omochimetaru 14-Jan-20 01:42 AM
Hello Everyone, I am the author of the thesis Swift for Embedded Systems mentioned in this thread. After a long time, I finally got back to working on it so I would like to share some progress with you 🙂 It is still in an early phase, but I am currently not aware of any...
01:43
Swiftの組み込み対応してた人がソース公開した
01:44
thumbv7mに対応してるらしい
01:45
次はSTM32F439ZIをやるみたい
Avatar
kateinoigakukun 14-Jan-20 02:18 AM
やっぱりバイナリサイズがネックらしいですね
Avatar
omochimetaru 14-Jan-20 02:19 AM
単純に小さい標準ライブラリを作るしか無いよねえ?
Avatar
kateinoigakukun 14-Jan-20 02:20 AM
メインプログラム側で使ってないstdlibの関数をストリップする方法があれば良いんじゃないですかね
Avatar
omochimetaru 14-Jan-20 02:21 AM
う〜んそうか、それがきれいだね
Avatar
kateinoigakukun 14-Jan-20 02:21 AM
動的にキャストされる可能性をSwiftレベルで検証して、stdlib側のPWTを消し去る
Avatar
omochimetaru 14-Jan-20 02:21 AM
動的な型情報経由のアクセスとかがあるから、
02:22
リンカーレベルではできなくて
02:22
Swiftコンパイラレベルで型の利用関係を抽出する必要がありそう
Avatar
kateinoigakukun 14-Jan-20 02:24 AM
モジュール内では必要な時だけメタデータを出力するような作りになってるっぽい
02:24
@helje5 @compnerd Sorry, I misunderstood. The compiler only emits metadata records by need. In WMO, if nothing uses the class, then nothing should be triggering its emission to begin with
Avatar
omochimetaru 14-Jan-20 02:32 AM
あ〜、それはそうだよね、LLVM-IRとか見てると。
02:32
ああそうか、だから、仕組みとしては存在しているけど
02:32
一つのモジュール(ソースファイル?)をビルドする単位での話で
02:33
一度ビルドしちゃったモジュールをリンクする時にそういうのがないって話なのかな
Avatar
kateinoigakukun 14-Jan-20 03:03 AM
そうですねー
Avatar
omochimetaru 14-Jan-20 03:04 AM
The compiler only emits metadata records by need.
↑ここの仕組みってLLVM側っぽい感じがしているけどどうなんかなあ
03:05
あ〜いや、そんな事無いかも・・・
03:05
IRGen::emitLazyXXXX系ってこのためにあるデザインかも
Avatar
kateinoigakukun 14-Jan-20 03:05 AM
あー、どうなんだろう… メタデータって大抵llvm irレベルでDCEしないでくれアトリビューションがついてる気がする (edited)
Avatar
omochimetaru 14-Jan-20 03:06 AM
IRGenの中身ってとにかくひたすら getCachedResultOrEmit みたいなものを経由するようになってて
03:06
その返り値が llvm::Value * なんだよね
Avatar
kateinoigakukun 14-Jan-20 03:07 AM
なるほどなるほど
Avatar
omochimetaru 14-Jan-20 03:07 AM
出発点としてソースファイルのtop level functions/typesに対してループして
03:07
コード生成時に細かいSILType とか出会うたびにそれが呼ばれるから
03:07
そんときにその場でemitしたり、lazyEmit登録しておいたりして
03:07
最後にlazy登録された奴らのemitが来る
03:08
なんかそれで使うものだけ吐く形になる気がしてきた
Avatar
kateinoigakukun 14-Jan-20 03:08 AM
だから出力しないのとシンボル削除する機能は全く別の機構が必要なのか
Avatar
omochimetaru 14-Jan-20 03:08 AM
あ、そうだね、今の話はリンクタイムは全く使えんな・・・
Avatar
kateinoigakukun 14-Jan-20 03:09 AM
たしか今年のLLVM MTGでSwiftのLTOの話があった気がする
Avatar
omochimetaru 14-Jan-20 03:09 AM
マジ
03:10
Link Time Optimization For Swift - Jin Lin [ Video ] [ Slides ]
03:10
Those unused code and data cannot be eliminated easily by the compiler optimizations since they are recorded in llvm.used data structure
03:10
We introduce a novel building pipeline that eliminates the protocol from swift class by leveraging the link time optimization in existing LLVM compiler
03:10
ほんとだw
Avatar
kateinoigakukun 14-Jan-20 03:11 AM
まさにこれだ
Avatar
omochimetaru 14-Jan-20 03:11 AM
The experiment shows that this novel approach reduces the code size of some commercial iOS app by 2%.
03:11
後で見る
07:43
↑急に来た感
07:44
pitchはここか
Avatar
nanasi 19-Jan-20 02:34 AM
Enum cases as protocol witnesses Proposal: SE-XXXX Author: Suyash Srijan Review Manager: [TBD] Status: Awaiting Review Implementation: apple/swift#28916 Bug: SR-3170 Introduction Allow enum cases to satisfy static protocol requirements. Swift-evolution thread: Enum ca...
02:34
pitch が来た😍
Avatar
omochimetaru 23-Jan-20 02:15 PM
@koher
Swift 6 での Windows サポートあるんじゃないの?
Apple公式にWindows版の保守する可能性出てきましたね
Avatar
koher 23-Jan-20 02:15 PM
Apple というか、 Swift 公式じゃない?
14:16
compnerd さんは Google の人っぽい。
14:16
Chris Lattner も Google だし、 Core Team も Apple 一色じゃなくなってきた。
Avatar
omochimetaru 23-Jan-20 02:17 PM
あれ、compnerdさんFacebookじゃなかったっけ
Avatar
koher 23-Jan-20 02:17 PM
2019 年から Google になってる。
Avatar
omochimetaru 23-Jan-20 02:17 PM
そうだったのか
Avatar
koher 23-Jan-20 02:17 PM
お、先月からだ。
Avatar
omochimetaru 23-Jan-20 02:17 PM
S4TFのWindowsサポートの話題もちょろっと見かけたし両方やってそうだな
Avatar
koher 23-Jan-20 02:18 PM
先月まで Facebook で、今月から Google
14:18
Refine Swift’s implementation and capabilities to allow it to be used for low-level systems programming (or in constrained environments) and in important domains like services and machine learning
14:19
S4TF も意識されてそう。
Avatar
omochimetaru 23-Jan-20 02:20 PM
ほんとだ〜
14:20
先月ってことはこの間のLLVM MTGで登壇したときはFacebookか
Avatar
koher 23-Jan-20 02:20 PM
Ownership, Concurrency, Variadic Generics, Windows サポートって実現したら Swift 6 すごすぎない?
14:21
ABI 安定化も終わってようやく本当の Swift 1.0 って感じだね。
Avatar
omochimetaru 23-Jan-20 02:21 PM
あと、Battery Included的なこともやりたいみたいですね
14:22
最近StdLibのBeta Packageの話もしてるし。
Avatar
koher 23-Jan-20 02:22 PM
あー書いてあったね
Avatar
omochimetaru 23-Jan-20 02:23 PM
うーんスゴイというか、最低限が揃うという感じ・・・
Avatar
koher 23-Jan-20 02:23 PM
Some examples of the latter include cultivating the critical ingredients needed for using Swift for developing services as well as libraries like Swift Numerics which are essential for a variety of use cases ranging from scientific computing to machine learning.
14:23
いや、これまでの ABI 安定化中心でなかなか進まなかった色んなものが一気に進む感じ。
Avatar
omochimetaru 23-Jan-20 02:23 PM
そうですね。1.0感はありますね。
Avatar
koher 23-Jan-20 02:23 PM
Concurrency って async/await だけじゃなく actor までいくかな?
14:24
actor までいけば Logic Failure をハンドリングできるようになるかも。
Avatar
omochimetaru 23-Jan-20 02:24 PM
うーん、async/awaitしばらく使ってみてから議論しようみたいになりそう
Avatar
koher 23-Jan-20 02:25 PM
あー個人的には Reverse Generics を進めてほしい。
Avatar
omochimetaru 23-Jan-20 02:25 PM
スレッドの感じだと
14:25
ニーズを提示しないと進みそうにないですね
14:25
Adrian Meisterさんが
14:25
Generics系いろいろ進めようぜ〜みたいに書き込んでるけど
14:26
Joe Groffのレスみてると。
14:26
VariadicGenericsだけ具体的に書かれてるのはSwiftUIのAPIがヤバい事になってるからだと思う。
14:26
10個までしか並べられない。
Avatar
koher 23-Jan-20 02:27 PM
Opaque 型パラサポートもしないと Opaque Type も中途半端だけど、それできても Reverse Generics ないと↓とかできなくない?普通に機能足りてないと思うんだけど・・・。
Avatar
omochimetaru 23-Jan-20 02:27 PM
Cristian Garcia This. Resorting to the Any* erasure types feels wrong. This should be fixed.
↑コレは本当にそうなので parameterized existentialは進んだらいいなあ。
Avatar
koher 23-Jan-20 02:27 PM
func makeAnimalPair() -> <A: Animal> (A, A) { ... }
Avatar
omochimetaru 23-Jan-20 02:28 PM
できないのはそうで、それをやりたくなった具体的なシナリオで説得する必要がありそうな雰囲気を感じる。
Avatar
koher 23-Jan-20 02:29 PM
うーん。 Opaque 型パラはやる感じなのかな?そっちはイテレータ隠蔽にいるし。
14:30
ああ違う
14:30
Foo<some Animal>some Animal<.Foo == Bar> は別の話だった
Avatar
omochimetaru 23-Jan-20 02:30 PM
Combineでerasure使うところ、assoctype対応したORTが欲しそうな気はする
Avatar
koher 23-Jan-20 02:30 PM
どっちもほしいけど、イテレータは後者だ。
14:32
あと any も進めてほしいなぁ。 any はシンタックスだけの話だから対応は一番簡単だと思う。
Avatar
omochimetaru 23-Jan-20 02:34 PM
実装するものは結構たくさんあると思いますよ
Avatar
koher 23-Jan-20 02:35 PM
Generalized Existential じゃなくて、 Existential に any 必須にするだけで?
Avatar
omochimetaru 23-Jan-20 02:35 PM
ああ〜、そっちか。
Avatar
koher 23-Jan-20 02:35 PM
パーサだけの話じゃないの?コンバータもあるかもだけど。 (edited)
14:39
Type Erasure 不毛すぎるからいいかげん Generalized Existential もほしい気もするけど、これから新しいプラットフォームに広げるならプロトコルのインタフェース化を防ぐためにしばらくなくてもいい気もする・・・。
14:40
まあでも Self-conformance がないから、 Generalized Existential があってもインタフェース的には使えないか。
14:40
any Sequence<.Element == Int> 型引数に any Sequence<.Element == Int> を渡せないし。 (edited)
Avatar
omochimetaru 23-Jan-20 02:41 PM
あー
14:41
いや、なので、そこは
Avatar
koher 23-Jan-20 02:41 PM
some Sequence<.Element == Int> なら渡せるのおもしろいな。
Avatar
omochimetaru 23-Jan-20 02:42 PM
Generalizedを入れるタイミングで、Self-conformanceは
14:42
ユーザ定義できるようにすべきですね
14:42
extension any Equatable: Equatable { static func ==... }
Avatar
koher 23-Jan-20 02:42 PM
ユーザ定義はできるようにするとしても、標準ライブラリで any SequenceSequence 準拠するかな?
Avatar
omochimetaru 23-Jan-20 02:43 PM
AnySequenceは今も is Sequenceですよね
14:43
それにstatic memberが無いからself-coformanceの実装は自明だと思う (edited)
Avatar
koher 23-Jan-20 02:43 PM
うん、でも AnySequenceSubSequence も決まってるしなー。
14:43
AnyCollection とか Index まで決まってるし。
Avatar
omochimetaru 23-Jan-20 02:44 PM
それは、選べなきゃいけなくて
14:44
any Sequence<Element = Int>any Sequence<Element = Int, SubSequence = Array<Int>>
14:44
別の型だと思う。 (edited)
14:45
あーでもプロトコル準拠するなら全部埋めなきゃいけないのか。
14:45
あ、でも、AnySequenceはそうなってるか。
Avatar
koher 23-Jan-20 02:45 PM
あれ?
Avatar
omochimetaru 23-Jan-20 02:45 PM
今のAnySequenceはSubSequenceもAnySequenceだから
Avatar
koher 23-Jan-20 02:45 PM
SubSequenceCollection
14:45
この前も勘違いしたんだった
14:46
SequenceIteratorElement しか持ってないんだった。
Avatar
omochimetaru 23-Jan-20 02:46 PM
あれ、そうだっけ。それならまあそっちはOKだ。
14:46
typealias AnySequence<E> = any Sequence<Element = T, SubSequence = any Sequence... // ←ここが再帰すると書けないな? (edited)
14:47
この辺りとか SubSequence 出てこない。
14:47
じゃあ Collection の話として
14:48
let c: any Collection<.Element == Int> = [2, 3, 5] let sc = c[1...]
14:48
このとき sc の型はどうなるの?
14:49
any Collection<.Element == Int> (edited)
Avatar
omochimetaru 23-Jan-20 02:49 PM
AnyCollection.SubSequenceAnyCollection だから
14:50
えっとまず、僕の考えだと
14:50
↑のコードについては、 scの型は SubSequenceを指定してないから、 Any になるか、コンパイルエラーのどっちか。
14:50
いや、 some Collection かも。
14:51
一番理論的に正しいのは some Collection じゃないかしら?
Avatar
koher 23-Jan-20 02:51 PM
some は無理じゃない?
14:51
c の型が実行時にしか決まらないから
Avatar
omochimetaru 23-Jan-20 02:51 PM
あ、何が入るかわからないか。
Avatar
koher 23-Jan-20 02:51 PM
うん
Avatar
omochimetaru 23-Jan-20 02:51 PM
じゃあ正しいのはコンパイルエラーだけど
14:51
現状のAnyCollectionに寄せるのであれば
14:51
get操作はAnyとして取れるけど
14:51
set操作をした場合は暗黙のダウンキャストが挿入されて
14:51
型不一致ならクラッシュかな?
Avatar
koher 23-Jan-20 02:52 PM
associatedtype SubSequence : Collection = Slice<Self> where Self.Element == Self.SubSequence.Element, Self.SubSequence == Self.SubSequence.SubSequence
14:52
Any まではいかなくて、↑にマッチする最も抽象的な型?
Avatar
omochimetaru 23-Jan-20 02:52 PM
指定していない associatedtypeについては Never を指定したことにして呼び出せないっていうのが良いんじゃないか
14:52
あ〜、そうですね、それにマッチするExistentialにできるかな?
14:53
でもやっぱりsetしたときにダウンキャストが必要だなあ。内部では真の型があるのだから。
Avatar
koher 23-Jan-20 02:53 PM
あー
Avatar
omochimetaru 23-Jan-20 02:53 PM
あれーやっぱりsomeにできませんかね?
Avatar
koher 23-Jan-20 02:53 PM
covariant position と contravariant position で
Avatar
omochimetaru 23-Jan-20 02:53 PM
この場合、identityがlet c に束縛されたsomeです。
Avatar
koher 23-Jan-20 02:54 PM
どっち側に振れるかが逆になるのかな?
14:54
contravariant position だと Never 側?
Avatar
omochimetaru 23-Jan-20 02:55 PM
var c だったら、再代入のたびに identityが変わる。
Avatar
koher 23-Jan-20 02:56 PM
protocol Foo { associatedtupe X var x: X { get set } }
14:57
var foo: any Foo = ... let x = foo.x foo.x = ...
14:57
↑で考えると、コンパイル通るなら x の型は Any で、 set のときは Never じゃないといけないよね?
Avatar
omochimetaru 23-Jan-20 02:58 PM
厳しくいくならそうだと思います、つまり代入できない。
Avatar
koher 23-Jan-20 02:59 PM
protocol Foo { associatedtupe X: Bar var x: X { get set } }
var foo: any Foo = ... let x = foo.x
これなら xany Bar でいける。
Avatar
omochimetaru 23-Jan-20 02:59 PM
やっぱり x の型は 空の some  じゃないですかね?
15:00
var foo に対しての some。
15:00
get foo.xset foo.x は、同じ型 同じだけど具体的に見えないから some。
15:00
var x に再代入があったら、そこから仕切り直し。
Avatar
koher 23-Jan-20 03:00 PM
そこを some にしようとすると x の型をコンパイル時に決定しないといけないんじゃない?
Avatar
omochimetaru 23-Jan-20 03:00 PM
いいえ
15:00
some は、コンテナに入ってますよ。
15:01
真の型がわかるときは最適化して置換できるだけで
15:01
実行表現としてのsomeは <T> とかと同じです。
Avatar
koher 23-Jan-20 03:01 PM
いや、やっぱおかしくて
Avatar
omochimetaru 23-Jan-20 03:01 PM
そうでないと、ABI互換を保ちながらライブラリの返す真の型を後のバージョンで変えられない。
Avatar
koher 23-Jan-20 03:02 PM
var foo: any Foo = Foo1() let x = foo.x foo = Foo2() foo.x = x
15:02
↑ができちゃだめだから
15:02
setNever じゃないと。
Avatar
omochimetaru 23-Jan-20 03:03 PM
いいえ、それはできないんです
Avatar
koher 23-Jan-20 03:03 PM
foosome なら get して set できていいけど、 any だからインスタンスから差し替えられる。
Avatar
omochimetaru 23-Jan-20 03:03 PM
foo = Foo2() の行がある時点で
15:03
その行より後ろの foo は別のidentityであることが静的に解析できるから。
Avatar
koher 23-Jan-20 03:03 PM
えー、同じ foo.x の型が変わっちゃだめじゃない?
Avatar
omochimetaru 23-Jan-20 03:04 PM
var foo: any Foo = Foo1() let x = foo.x foo = Foo2() foo.x = x
↑これは↓のような解釈
let foo_1: any Foo = Foo1() let x = foo_1.x let foo_2 = Foo2() foo_2.x = x // foo_2.Xとfoo_1.Xは違う型だからコンパイルエラー
Avatar
koher 23-Jan-20 03:04 PM
それよりも setNever 扱いの方が自然だと思うけど。
15:05
同じ var の型が変わるというのは変だと思う。
Avatar
omochimetaru 23-Jan-20 03:06 PM
でも、そもそも existential が、
15:06
型を値レベルで閉じ込める仕組みだから
15:06
値単位で型が変わるのは理論的に正しいと思う
15:06
仕様としてわかりにくいからやめとこうっていう意見はわかりますけど。
15:07
ただその場合、現状のAnyCollectionで可能な
var c: AnyCollection<Int> = foo() print(c[c.startIndex])
Avatar
koher 23-Jan-20 03:07 PM
値の型がわからなくてもうまく動くように型システムが働くのが自然だと思うけどなぁ。
Avatar
omochimetaru 23-Jan-20 03:07 PM
↑これができるようになる理屈を用意しないといけないですね
15:07
contravariant positionがNeverなのであれば subscript get ができなくなっちゃうから。 (edited)
15:08
で、現状のAnyCollectionには問題があって
Avatar
koher 23-Jan-20 03:08 PM
上界・下界とも決められる仕組みが必要なのかな?
Avatar
omochimetaru 23-Jan-20 03:08 PM
var c: AnyCollection<Int> = foo() let s = c.startIndex print(c[s]) // 絶対OK c = goo() print(c[s]) //クラッシュしうる
(edited)
15:08
↑こういう問題があるんです
15:09
で、僕のさっきのアイデアだと、これを正しく、 絶対OKの方はコンパイルできて、クラッシュしうる方はコンパイルできない
15:09
って型チェックができる。
Avatar
koher 23-Jan-20 03:09 PM
うーん、 Type Erasure はワークアラウンドだし、必ずしも Existential がそれを踏襲しなければいけないわけじゃないと思うけど。
15:11
any Collection<.Element == Foo, .Index == Int> とかでもいいわけだし。
Avatar
omochimetaru 23-Jan-20 03:13 PM
それはそれで、出来たほうが良いと思います
15:13
そうじゃないと、もし↑のsomeの案だと、 たとえIndexが同じであっても、コンパイルエラーになっちゃうから、
15:13
.Index == Int の指定があるなら、再代入の前後でIndexに型互換性があることをチェックできる。
15:14
.Index == Hoge の指定を省略した時の挙動を考えてました。
Avatar
koher 23-Jan-20 03:14 PM
protocol Foo { associatedtype X: Bar where Baz: X var x: X { get set } }
15:14
うん、で、省略したときは Index が contravariant position で Never になっちゃうのでいいんじゃない?ってこと。
Avatar
omochimetaru 23-Jan-20 03:14 PM
あれ、そこにwhere付けられましたっけ。
Avatar
koher 23-Jan-20 03:15 PM
コンパイラクラッシュしたw
Avatar
omochimetaru 23-Jan-20 03:15 PM
oh・・・
Avatar
koher 23-Jan-20 03:15 PM
↑が書ければ、 Never まで飛ばずに contravariant position を any Baz にとどめられる。
Avatar
omochimetaru 23-Jan-20 03:15 PM
ちょっと、where無しで、書いてもらえますか、書きたかった意図が読み取れない (edited)
Avatar
koher 23-Jan-20 03:16 PM
Baz: X: Bar って関係ってこと
15:16
Baz < X < Bar って書いた方がいいかな?
15:16
Never < Baz < X < Bar < Any
15:17
上界と下界を指定できて (edited)
Avatar
omochimetaru 23-Jan-20 03:17 PM
うーん、それやっても、
15:17
getで返ってくるのが any Bar で
15:17
setで要求するのがany Bazだから
Avatar
koher 23-Jan-20 03:17 PM
うん
Avatar
omochimetaru 23-Jan-20 03:17 PM
どっちにしろ、取ったものを渡せないですよね?
Avatar
koher 23-Jan-20 03:17 PM
うん
15:17
上界と下界が一致するとき(つまり == )だけ
Avatar
omochimetaru 23-Jan-20 03:17 PM
型安全性にするならそれでいいけど
Avatar
koher 23-Jan-20 03:17 PM
get したものを set できる。
Avatar
omochimetaru 23-Jan-20 03:17 PM
AnyCollectionみたいに実行時クラッシュはするけど
15:17
「正しいときは実行できる」ほうがいいきもする。
Avatar
koher 23-Jan-20 03:18 PM
いや、 AnyCollection はデフォルト型パラがなかったから、しかたなく型パラを制限してるだけで
Avatar
omochimetaru 23-Jan-20 03:18 PM
コンパイルエラーだと、実際に正しいコード
let c: any Collection<E = Int> = foo() print(c[c.startIndex])
これすら使えなくなっちゃう
(edited)
Avatar
koher 23-Jan-20 03:18 PM
本当はすべての associatedtype を型パラに持ってた方が良かったと思うんよね。
15:19
get して set が必要なときは指定すればいいんだから。
Avatar
omochimetaru 23-Jan-20 03:19 PM
let c: any Collection<E = Int, I = Int> = foo() print(c[c.startIndex])
↑こうしろって事ですか?
Avatar
koher 23-Jan-20 03:19 PM
うん。
Avatar
omochimetaru 23-Jan-20 03:19 PM
ふ〜む。なるほど・・・
15:20
書くのがめんどくさそうだけど正しくはありますね。
Avatar
koher 23-Jan-20 03:20 PM
うん、めんどうだけど、 Existential にそれくらいのペナルティあってもちょうど良さそう。
15:21
多用するときは typealias だって書けるわけだし。
Avatar
omochimetaru 23-Jan-20 03:23 PM
上界と下界が一致するとき(つまり == )だけ
これってありえますかね
15:24
うーんありえるか?意味的に変な気がしたけど
Avatar
koher 23-Jan-20 03:24 PM
@swift-5.1.5
class C1 {} class C2: C1 {} class C3: C2 {} protocol Foo { associatedtype X: C1 where C3: X var x: X { get set } }
Avatar
swift51 BOT 23-Jan-20 03:24 PM
exit status: 134 with stderr:
swift: /home/buildnode/jenkins/workspace/oss-swift-5.1-package-linux-ubuntu-16_04/llvm/include/llvm/Support/Casting.h:255: typename cast_retty<X, Y *>::ret_type llvm::cast(Y *) [X = swift::DependentMemberType, Y = swift::TypeBase]: Assertion `isa<X>(Val) && "cast<Ty>() argument of incompatible type!"' failed. Stack dump: 0. Program arguments: /usr/bin/swift -frontend -interpret - -disable-objc-interop -I /Libraries/.build/x86_64-unknown-linux/debug -I /Libraries/.build/checkouts/swift-nio/Sources/CNIOAtomics/include -I /Libraries/.build/checkouts/SwiftBacktrace/Sources/CSwiftBacktrace/include -I /Libraries/.build/checkouts/SwiftBacktrace/Sources/Clibunwind/include -I /Libraries/.build/checkouts/OpenCombine/Sources/COpenCombineHelpers/include -module-cache-path /Libraries/.build/x86_64-unknown-linux/debug/ModuleCache -D DEBUG -Xcc -fmodule-map-file=/Libraries/.build/x86_64-unknown-linux/debug/CNIOAtomics.build/module.modulemap -Xcc -fmodule-map-file=/Libraries/.build/checkouts/SwiftBacktrace/Sources/CSwiftBacktrace/include/module.modulemap -Xcc -fmodule-map-file=/Libraries/.build/checkouts/SwiftBacktrace/Sources/Clibunwind/include/module.modulemap -Xcc -fmodule-map-file=/Libraries/.build/x86_64-unknown-linux/debug/COpenCombineHelpers.build/module.modulemap -module-name main -lLibraries 1. While type-checking 'Foo' (at <stdin>:5:1) 2. While validating 'Foo' (at <stdin>:5:1) /usr/bin/swift[0x493d544] /usr/bin/swift[0x493b160] /usr/bin/swift[0x493d968] /lib/x86_64-linux-gnu/libpthread.so.0(+0x11390)[0x7fe4b6470390] /lib/x86_64-linux-gnu/libc.so.6(gsignal+0x38)[0x7fe4b4995428] /lib/x86_64-linux-gnu/libc.so.6(abort+0x16a)[0x7fe4b499702a] /lib/x86_64-linux-gnu/libc.so.6(+0x2dbd7)[0x7fe4b498dbd7] /lib/x86_64-linux-gnu/libc.so.6(+0x2dc82)[0x7fe4b498dc82] /usr/bin/swift[0x1447f41] /usr/bin/swift[0x1447cef] /usr/bin/swift[0x1458fb0] /usr/bin/swift[0x144c03f] /usr/bin/swift[0x1470c04] /usr/bin/swift[0x14ce5b9] /usr/bin/swift[0x1455f72] /usr/
Avatar
omochimetaru 23-Jan-20 03:24 PM
多用するときは typealias だって書ける
まあそうかあ
15:25
erausreを自作する代わりにちょっと面倒なtypealiasを書くならだいぶ楽。
Avatar
koher 23-Jan-20 03:25 PM
erasure自作してると、generalized existentialないのおかしいだろって気持ちになるもんねw
Avatar
omochimetaru 23-Jan-20 03:28 PM
ボイラープレートもいいところですからねえ
15:30
@swiftbot
protocol P{} protocol Q { associatedtype P: X }
Avatar
swiftbot BOT 23-Jan-20 03:30 PM
Author icon
omochimetaru
protocol P{} protocol Q { associatedtype P: X }
Version:
swift-5.1.3-RELEASE
Output:
Error:
/usercode/main.swift:3:21: error: use of undeclared type 'X' associatedtype P: X ^
Avatar
omochimetaru 23-Jan-20 03:30 PM
あーそっか、最初に名前が来るから、lower boundの書きようが無いのか
Avatar
koher 23-Jan-20 03:31 PM
うん、なので where
Avatar
omochimetaru 23-Jan-20 03:32 PM
@swiftbot
protocol P1 {} protocol P2 {} protocol Q { associatedtype X where X: P1, X: P2 }
Avatar
swiftbot BOT 23-Jan-20 03:32 PM
Author icon
omochimetaru
protocol P1 {} protocol P2 {} protocol Q { associatedtype X where X: P1, X: P2 }
Version:
swift-5.1.3-RELEASE
Output:
Error:
Avatar
omochimetaru 23-Jan-20 03:32 PM
名前だけ書いてwhereで条件付けるのはいいのか。
Avatar
koher 23-Jan-20 03:33 PM
@swift-5.1.5
class C1 {} class C2: C1 {} class C3: C2 {} protocol Foo { associatedtype X where C3: X var x: X { get set } }
Avatar
swift51 BOT 23-Jan-20 03:33 PM
exit status: 134 with stderr:
swift: /home/buildnode/jenkins/workspace/oss-swift-5.1-package-linux-ubuntu-16_04/llvm/include/llvm/Support/Casting.h:255: typename cast_retty<X, Y *>::ret_type llvm::cast(Y *) [X = swift::DependentMemberType, Y = swift::TypeBase]: Assertion `isa<X>(Val) && "cast<Ty>() argument of incompatible type!"' failed. Stack dump: 0. Program arguments: /usr/bin/swift -frontend -interpret - -disable-objc-interop -I /Libraries/.build/x86_64-unknown-linux/debug -I /Libraries/.build/checkouts/swift-nio/Sources/CNIOAtomics/include -I /Libraries/.build/checkouts/SwiftBacktrace/Sources/CSwiftBacktrace/include -I /Libraries/.build/checkouts/SwiftBacktrace/Sources/Clibunwind/include -I /Libraries/.build/checkouts/OpenCombine/Sources/COpenCombineHelpers/include -module-cache-path /Libraries/.build/x86_64-unknown-linux/debug/ModuleCache -D DEBUG -Xcc -fmodule-map-file=/Libraries/.build/x86_64-unknown-linux/debug/CNIOAtomics.build/module.modulemap -Xcc -fmodule-map-file=/Libraries/.build/checkouts/SwiftBacktrace/Sources/CSwiftBacktrace/include/module.modulemap -Xcc -fmodule-map-file=/Libraries/.build/checkouts/SwiftBacktrace/Sources/Clibunwind/include/module.modulemap -Xcc -fmodule-map-file=/Libraries/.build/x86_64-unknown-linux/debug/COpenCombineHelpers.build/module.modulemap -module-name main -lLibraries 1. While type-checking 'Foo' (at <stdin>:5:1) 2. While validating 'Foo' (at <stdin>:5:1) /usr/bin/swift[0x493d544] /usr/bin/swift[0x493b160] /usr/bin/swift[0x493d968] /lib/x86_64-linux-gnu/libpthread.so.0(+0x11390)[0x7f433d746390] /lib/x86_64-linux-gnu/libc.so.6(gsignal+0x38)[0x7f433bc6b428] /lib/x86_64-linux-gnu/libc.so.6(abort+0x16a)[0x7f433bc6d02a] /lib/x86_64-linux-gnu/libc.so.6(+0x2dbd7)[0x7f433bc63bd7] /lib/x86_64-linux-gnu/libc.so.6(+0x2dc82)[0x7f433bc63c82] /usr/bin/swift[0x1447f41] /usr/bin/swift[0x1447cef] /usr/bin/swift[0x1458fb0] /usr/bin/swift[0x144c03f] /usr/bin/swift[0x1470c04] /usr/bin/swift[0x14ce5b9] /usr/bin/swift[0x1455f72] /usr/
Avatar
koher 23-Jan-20 03:33 PM
lower bound だけで死ぬ
Avatar
omochimetaru 23-Jan-20 03:34 PM
報告だ
Avatar
koher 23-Jan-20 03:40 PM
lower boundsで調べてもそれっぽいバグレポないね
Avatar
omochimetaru 23-Jan-20 03:42 PM
検索してみたけど、無さそう
15:42
すごいシンプルだけど普通やらないからマジで誰も気づいてないのでは
Avatar
koher 23-Jan-20 03:43 PM
$ cat lower.swift class C1 {} class C2: C1 {} protocol Foo { associatedtype X where C2: X } $ swiftc lower.swift Stack dump: ... <unknown>:0: error: unable to execute command: Segmentation fault: 11 <unknown>:0: error: compile command failed due to signal 11 (use -v to see invocation)
(edited)
Avatar
omochimetaru 23-Jan-20 03:44 PM
離席します
Avatar
koher 23-Jan-20 03:57 PM
15:58
自分のバグチケット一覧見てるとなんでこんな変なコーナーケースばっかり突いてるのかという気持ちになるな・・・。コーナーだからバグが見つかるんだろうけど。
Avatar
koher 23-Jan-20 04:11 PM
Scala だと :> 使って簡単に lower bound を書けるのかぁ。
class A {} class B extends A {} trait T[-X >: B] { def bar(x: X): Unit } class C extends T[A] { def bar(x: A): Unit = { println("C.bar: " + x) } } val c: C = new C() val t: T[B] = c t.bar(new B())
16:13
C.bar: Playground$B@16418d1a
Avatar
koher 24-Jan-20 01:26 AM
@swift-5.0.3
class C1 {} class C2: C1 {} protocol Foo { associatedtype X where C2: X }
01:26
お、ほんとだ。 Swift 5 だと通る。
Avatar
koher 24-Jan-20 01:35 AM
This looks like a regression because we used to correctly diagnose this in Swift 5, but since 5.1 this is crashing.
Avatar
omochimetaru 24-Jan-20 01:36 AM
テストケース漏れてて壊れしちゃったやつでしたね
Avatar
koher 24-Jan-20 01:37 AM
we used to correctly diagnose this in Swift 5
テストケースないのにどうやって "diagnose" したんだろう?
Avatar
omochimetaru 24-Jan-20 01:38 AM
このdiagnoseは
01:38
optimize and diagnose のコンパイラ用語の方のdiagnoseじゃないですか?
01:39
あれ、でも普通に5でも通るのか
01:39
エラーが出たりして結局できないよって話かと思った
Avatar
rintaro 24-Jan-20 01:41 AM
error: type 'C2' constrained to non-protocol, non-class type 'Self.X'
Avatar
omochimetaru 24-Jan-20 01:42 AM
@swift-5.0.3
class C1 {} class C2: C1 {} protocol Foo { associatedtype X where C2: X } print(1)
Avatar
rintaro 24-Jan-20 01:42 AM
swift-5.0.3 ボットが死んでる?
Avatar
omochimetaru 24-Jan-20 01:42 AM
そういうことかwややこしい
01:43
rintaroさんはどうやって5系を叩いたんですか
01:43
Xcodeたくさん入れてる?
Avatar
rintaro 24-Jan-20 01:43 AM
10.3 が手元にインストールされてます。
Avatar
omochimetaru 24-Jan-20 01:44 AM
01:45
なるほど。見てみたら僕も10.2もってたわ。
01:45
じゃあやっぱり、さっきのコメントの英文の diagnose は↑のエラーメッセージが出ることを
01:45
指しているんじゃないかしら。
Avatar
koher 24-Jan-20 01:48 AM
ボット落ちてたのか・・・
Avatar
omochimetaru 24-Jan-20 01:48 AM
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
Avatar
koher 24-Jan-20 01:48 AM
なるほど < diagnose
Avatar
omochimetaru 24-Jan-20 01:48 AM
↑似たようなやつはあるけど、同じのはないな。
Avatar
koher 24-Jan-20 01:50 AM
"non-class type" は、 X: AnyObject でもダメなのかな? X 自体はクラスじゃないしダメ?
Avatar
omochimetaru 24-Jan-20 01:51 AM
これ右側が駄目なんですね
01:51
C: P の右側のPはプロトコルじゃないといけないから ←これは誤りか (edited)
01:51
associatedtype自体を コロンの右に書く時点で駄目なんだ
01:53
01:53
だめらしい
01:53
微妙に変な気がするけどw
01:54
: AnyObject なら絶対クラスだよな。文言からすると protocol じゃないのが駄目なのか? (edited)
01:54
でも X: C は書けるしな。
01:55
う〜ん??
Avatar
omochimetaru 24-Jan-20 02:03 AM
ジェネリックパラメータに対してlower-boundが書ける場面ってもしかして無い??
02:04
コロンの左右反転で書けるつもりになってたけど実は書いたことがない気がしてきた
Avatar
koher 24-Jan-20 02:07 AM
書けなさそうな気がする。
Avatar
omochimetaru 24-Jan-20 02:07 AM
アハ体験
Avatar
koher 24-Jan-20 02:08 AM
書く機会はないけど、クロージャ型で引数の contravariance とか考えると、書けないとできないユースケースありそう。
Avatar
omochimetaru 24-Jan-20 02:08 AM
関数型同士の間ではちゃんと効くんですよね
Avatar
koher 24-Jan-20 02:09 AM
昨日の未指定 associatedtype は仮定の話だけど、クロージャ型は現実の課題。
Avatar
omochimetaru 24-Jan-20 02:09 AM
そうか、だから、ジェネリック型にそもそもvarianceがないからか?
Avatar
koher 24-Jan-20 02:09 AM
@swift-5.1.5
class C1 {} class C2: C1 {} func foo<X>(_ x: X) where C2: X {}
Avatar
swift51 BOT 24-Jan-20 02:09 AM
exit status: 1 with stderr:
<stdin>:4:29: error: type 'C2' constrained to non-protocol, non-class type 'X' func foo<X>(_ x: X) where C2: X {} ^
Avatar
omochimetaru 24-Jan-20 02:10 AM
書けないとできないユースケース
関数型自体のsubtypingで事足りちゃう気がする。
Avatar
nanasi 24-Jan-20 02:10 AM
class BaseViewController<Inherit: UIViewController>: Inherit {}
02:11
こういうケースのdiscussionはforumで見た覚えがあります。
Avatar
swift50 BOT 24-Jan-20 02:17 AM
exit status: 1 with stderr:
<stdin>:5:30: error: type 'C2' constrained to non-protocol, non-class type 'Self.X' associatedtype X where C2: X ^
02:17
exit status: 1 with stderr:
<stdin>:5:30: error: type 'C2' constrained to non-protocol, non-class type 'Self.X' associatedtype X where C2: X ^
Avatar
omochimetaru 24-Jan-20 02:19 AM
@nanasi それはlower-boundなだけでなくてCRTPになってるから更にややこしそうですね 僕も見た記憶がある
Avatar
koher 24-Jan-20 02:23 AM
↑の Inherit のは upper bound じゃない?それぞれ、 InferitBaseViewController の、 UIViewControllerInherit の。
Avatar
omochimetaru 24-Jan-20 02:24 AM
Inherit に対して BaseViewController というlower boundを与えているのでは さっきから実験している <X> C: X の形なので
02:24
パラメータの方を主語に見てますよね。
Avatar
koher 24-Jan-20 02:26 AM
Inherit 不定の状態がイメージできなかったけど、ジェネリック関数の中とかだといいのか。
Avatar
koher 24-Jan-20 02:39 AM
単純に↓だけで X に対する upper/lower bounds が効いてるか。
class C1 {} class C2<X: C1>: X { func foo(_ x: X) -> X { x } func bar() { let c1: C1 = foo(self) } }
02:40
さっきの形で lower bound が活きるのがどんなときかよくわからなくて考えてた。
Avatar
omochimetaru 24-Jan-20 02:40 AM
C++でよくやるんですけどそのとき必要になるのは自身の型を返すメソッドをもたせるときですね
Avatar
koher 24-Jan-20 02:41 AM
自身の型ってメタタイプってこと?
Avatar
omochimetaru 24-Jan-20 02:49 AM
template <Self> class RetainCounted<Self> { Self * retain() { ... } } class Cat: public RetainCounted<Cat> {} auto c1 = new Cat(); auto c2 = c1->retain(); // c2の型がCat*になってほしい
(edited)
02:49
ちょっと久しぶりで文法の自身ないですが↑これが頻出
Avatar
koher 24-Jan-20 03:09 AM
↑は c1Cat * だけど c2CatCat * ?とかわけわからなくなったので Swift に直してみたけど、↓みたいなことって理解で良い?
class X<K> { func foo() -> K { ... } } class C: X<C> {} let c1 = C() let c2 = c1.foo() // c2の型がCになってほしい
Avatar
omochimetaru 24-Jan-20 03:17 AM
あ〜やば。ポインタガバガバになってた。直しました。
03:17
あってます→Swift
03:18
これはSwiftでもコンパイルできるんですね。
03:18
さっきのはまたちょっと違う形なんだな。 (edited)
Avatar
koher 24-Jan-20 03:24 AM
@swift-5.1.5
class X<K> { var value: K { fatalError() } func foo() -> K { value } } class C: X<C> { override var value: C { self } } let c1 = C() let c2 = c1.foo() print(c2)
(edited)
Avatar
swift51 BOT 24-Jan-20 03:24 AM
main.C
(edited)
Avatar
koher 24-Jan-20 03:25 AM
実行もできた。
Avatar
nanasi 24-Jan-20 03:28 AM
たしかSwift5で出来るようになった気がします。
03:28
@swift-4.2.4
class X<K> { var value: K { fatalError() } func foo() -> K { return value } } class C: X<C> { override var value: C { return self } } let c1 = C() let c2 = c1.foo() print(c2)
(edited)
Avatar
swift42 BOT 24-Jan-20 03:28 AM
execution timeout with no output (edited)
Avatar
nanasi 24-Jan-20 03:31 AM
@swift-4.2.4
print("Hello world")
Avatar
swift42 BOT 24-Jan-20 03:31 AM
Hello world
Avatar
nanasi 24-Jan-20 03:32 AM
良かった、生きてた。
🙌 1
Avatar
omochimetaru 24-Jan-20 03:35 AM
4.2.4では無限ループしてたやつなのか。
Avatar
omochimetaru 24-Jan-20 05:49 AM
Refactor the implementation of function builders so they maintain the statement structure of the closure/function body to which they are applied. This replaces the previous &quot;fold everythin...
05:53
This replaces the previous "fold everything into a single expression" implementation with one that is better in several regards:
It allows generalization to statement kinds that cannot be expressed in a single expression, e.g., if let, although each of these will require work.
05:54
なんかよくなりそう
Avatar
omochimetaru 24-Jan-20 07:17 AM
This is really part of a much larger effort to improve #SwiftLang function builders, parts of which have been landing over the last ~6 months. So, I wrote up a summary of what we've been up to in this area: https://t.co/WXaXQlNC9O https://t.co/X5dldpviYi
07:17
ちょうど今アナウンス出たw
07:22
one-way constraintsもこれだったのか
Avatar
omochimetaru 24-Jan-20 07:56 AM
let書けるようになりそうなのか
It's scaffolding for supporting let declarations, if let, and switch statements to make function builders more expressive, although that generalization is still a work-in-progress.
07:58
For example, right now a single-expression closure can infer a closure result type: but a multi-statement closure does not: and one will have to provide some type annotations to make this code compile. We should be able to infer the result type of the closure to avoid the need for extra type annotations.
07:58
複数文クロージャの推論制限も外せるかもって言ってる!?
08:00
なんかよくわからないけど、これまでは推論ステージを分けて制御していた部分が、 推論器の内部でステージを制御できるような機能を与えることでいろいろうまくいくみたいな事な気がするな。
Avatar
omochimetaru 24-Jan-20 08:09 AM
Introduce the notion of &quot;one-way&quot; binding constraints of the form $T0 one-way bind to $T1 which treats the type variables $T0 and $T1 as independent up until the point where $T...
08:12
今までは 左の式のInt8とInt16のそれぞれで、右の式のInt8とInt16の型チェックをしてたから、2*2で4通りになってたけど、 左と右それぞれでInt8とInt16を確定してから組み合わせるから、 ?: の評価は4通りやるにせよ、計算効率がめっちゃよくなる?(適切にone-wayを入れられる場所なら)
Avatar
omochimetaru 29-Jan-20 01:45 AM
The Core Team has decided to reject proposal SE-0275: Allow more characters (like whitespaces and punctuations) for escaped identifiers.
01:45
サクッと通りそうな気がしてたけどRejectだ
Avatar
omochimetaru 31-Jan-20 02:49 AM
Hello, Swift community. The review of SE-0270 spanned three separate review periods, from November 11th, 2019, to January 28th, 2020. The latest round of review is here. Community feedback was highly positive on adding this feature in some form, but many details of the desi...
02:49
インデックスの集合のやつ、ついにAcceptedだ
Avatar
koher 31-Jan-20 04:22 AM
var numbers = Array(1...15) // Find the indices of all the even numbers let indicesOfEvens = numbers.subranges(where: { $0.isMultiple(of: 2) }) // Perform an operation with just the even numbers let sumOfEvens = numbers[indicesOfEvens].reduce(0, +) // sumOfEvens == 56
↑の numbers[indicesOfEvens] の結果のコレクションにおけるインデックスの扱いがどうなるんだろうと思ってたけど(他の言語みたいに array[range] のインデックスが 0 から始まらないのでどう整合性をとるのかなと)、↓こうなるのかぁ。
extension Collection { /// Accesses a view of this collection with the elements at the given /// indices. /// /// - Complexity: O(1) public subscript(subranges: RangeSet<Index>) -> DiscontiguousSlice<Self> { get } } extension MutableCollection { /// Accesses a mutable view of this collection with the elements at the /// given indices. /// /// - Complexity: O(1) to access the elements, O(*m*) to mutate the /// elements at the positions in `subranges`, where *m* is the number of /// elements indicated by `subranges`. public subscript(subranges: RangeSet<Index>) -> DiscontiguousSlice<Self> { get set } } /// A collection wrapper that provides access to the elements of a collection, /// indexed by a set of indices. public struct DiscontiguousSlice<Base: Collection>: Collection { /// The collection that the indexed collection wraps. public var base: Base { get set } /// The set of index ranges that are available through this indexing /// collection. public var subranges: RangeSet<Base.Index> { get set } /// A position in an `DiscontiguousSlice`. struct Index: Comparable { // ... } public var startIndex: Index { get } public var endIndex: Index { set } public subscript(i: Index) -> Base.Element { get } public subscript(bounds: Range<Index>) -> Self { get } }
(edited)
Avatar
omochimetaru 31-Jan-20 04:36 AM
Sliceだから元のコレクションと互換性のあるindexが来るから、
04:36
indexの数値だけ見ると飛び飛びになったりするってことかな。
Avatar
koher 31-Jan-20 04:38 AM
うん、そうだと思う。
04:40
これに限らず、 ArraySlice とかのインデックスの取り扱いって他言語と比較して特殊だと思うんだけど( 0 スタートになるのが多い)、その利点や不利益についてどこかで論じられてたりしたっけ?
Avatar
omochimetaru 31-Jan-20 04:59 AM
The review of SE-0265: Offset-Based Access to Indices, Elements, and Slices begins now and runs through October 21st, 2019. Reviews are an important part of the Swift evolution process. All review feedback should be either on this forum thread or, if you would like to keep y...
04:59
Michael ilsemanが
05:00
Offset based String Accessの変の話をやっていたときに
05:00
startIndexで扱うのがめんどくさいんだけど的な発言はちょいちょい見た気がするような
05:00
てか、フォーラムではたまに誰かが不満を書き込んでる感じはある
05:01
( 0 スタートになるのが多い)
個人的にそもそも無理だと思ってて
05:02
UTF-8 StringをCollectionとして扱おうと思ったら
05:02
indexからbyte offsetがO(1)で生成できないので
05:02
こうならざるを得なくないですか?
05:02
こう、というのは、「次のIndexを前のIndexに対するadvance操作で得る」体系ってこと。
Avatar
koher 31-Jan-20 05:03 AM
Index == Int に関しては?
Avatar
omochimetaru 31-Jan-20 05:03 AM
Sliceに関しても、[0] がスライスの開始点を現せるようにしたところで、 [1] ができちゃったらダメだし。 (edited)
Avatar
koher 31-Jan-20 05:03 AM
共通の Collection プロトコルを考える時点で無理かな?
Avatar
omochimetaru 31-Jan-20 05:03 AM
ダメそうな気がする、SliceのIndexを元のCollectionに渡して正当っていう仕様を
05:03
Index型によらずに整合取らないといけないから。
Avatar
koher 31-Jan-20 05:05 AM
つまり、 ArrayArraySlice については Collection にひきづられて今の仕様になってるってこと?ゼロスタートしないこと自体に何かの利益があるわけではなくて。
Avatar
omochimetaru 31-Jan-20 05:11 AM
という風に僕は勝手に納得しています
05:11
Arrayについては必ず0スタートじゃなかったっけ
05:12
ArraySliceだけ考えるなら、0スタートにすることはできたけど、一般的なCollectionとSliceの仕様を考えてそれに寄せてある。 (edited)
05:14
てか、そのような 「0から始まるやつ」 を提案しているのが
05:14
まさにSE-0265なような?
Avatar
koher 31-Jan-20 05:14 AM
Array は 0 スタートだけど、 ArraySlice もコピーなく 0 スタートにできるけどしない理由についてだね。 (edited)
Avatar
omochimetaru 31-Jan-20 05:15 AM
func fifth<C: Collection>(_ c: C) -> C.Element? { return c[.first + 4] } let array = [1,2,3,4,5,6,7,8,9] print(fifth(array)!) // 5 print(fifth(array[2...])!) // 7
05:16
fifth の中身では .first + 4 という形で 「4番目」と書いてるけど、
05:16
ちゃんと array でも array[2...] でも、「4番目」が得られてる。
05:17
ArraySlice を 0スタートにすると Slice にならなくなる。 ArraySliceがSliceでありながら0スタートになるようにすると、 StringのSliceが作れなくなる。
Avatar
koher 31-Jan-20 05:19 AM
そのあたりの整合性のためってのはわかるんだけど、それによって ArraySlice が使いにくくなってるとしたら悲しいから、 ArraySlice が 0 始まりじゃないことによる利点はないのかな?
05:19
それこそ Collection としてまとめて扱えること?
Avatar
omochimetaru 31-Jan-20 05:32 AM
ArraySlice が 0 始まりじゃないことによる利点は ArraySlice が Sliceに準拠することで、 ArraySliceもStrngSliceも同様に扱えるジェネリックなコードが書けるようになること、という理解・・・
Avatar
koher 31-Jan-20 05:50 AM
意外と ArraySlice が 0 はじまりじゃないこと自体が使いやすいケースもあると思うんだけどなぁ。
Avatar
rintaro 31-Jan-20 08:20 AM
ArraySlice の Index が元の Array のIndex である事を利用した例は https://developer.apple.com/documentation/swift/arrayslice にありますね (edited)
🙏 1
Avatar
omochimetaru 31-Jan-20 08:22 AM
if let i = absences.firstIndex(where: { $0 > 0 }) { // 1 let absencesAfterFirst = absences[(i + 1)...] // 2 if let j = absencesAfterFirst.firstIndex(where: { $0 > 0 }) { // 3 print("The first day with absences had \(absences[i]).") // 4 print("The second day with absences had \(absences[j]).") } }
08:23
なるほど・・・
08:23
Collectionに対してindexを探したりする時に、操作範囲の制御のためにArraySliceを使うと、結果がそのまま使える。
Avatar
rintaro 31-Jan-20 08:24 AM
結局スライスから取ったインデックスを元のコレクションにそのまま使えるっていうだけの話ではある。
Avatar
omochimetaru 31-Jan-20 08:24 AM
たしかに他の言語だとこういうfirstIndex 的なメソッドでは startIndex を引数に取る事が多いけど
08:25
スライスがある前提で全部のコレクションアルゴリズム系の関数からオフセット制御の引数をなくせるな。
Avatar
omochimetaru 31-Jan-20 08:35 AM
var array = [5, 4, 3, 2, 1] array[1...3].sort() print(array) // 5, 2, 3, 4, 1
へえ。
Avatar
koher 31-Jan-20 09:10 AM
そうそう、この一つ目みたいなやつは書いててあった気がする。二つ目のは考えたことなかった。おもしろいね。でもこれは subscript set で O(N) になる?
Avatar
omochimetaru 31-Jan-20 09:13 AM
Nをスライスの要素数だとすると、 処理対象のコピーがO(N), ソートがO(N logN)、結果の下記戻しがO(N) じゃないですかね
Avatar
koher 31-Jan-20 09:23 AM
ああ、 get もか。その subscript get/set の O(N) を省略できたら理想的なんだけどね。オーナーシップで扱えるようになるのかもしれないけど、そこらへんを賢くやってくれるとうれしいなぁ。
09:27
その二番目の sort の例ってどこから出てきたの? rintaro さんのリンク先になくない?
Avatar
omochimetaru 31-Jan-20 09:28 AM
ん?僕が書いたコードです
09:28
struct GetModify { var x: String = "👋🏽 Hello" var property: String { get { print("Getting",x); return x } modify { print("Yielding",x) yield &x print("Post yield",x) } } }
https://forums.swift.org/t/modify-accessors/31872
09:30
Modify accessorの例題に似た形をしてるのでownershipでいけるような気もするけど、 ArrayとArraySliceに関しては内部ストレージの共有とかあって、同じようにいける話なのかよくわかんないな。
Avatar
koher 31-Jan-20 09:34 AM
そうなのか。例として挙がってたのかと思った。
09:35
でもよく考えたらそのコード、インデックス維持が利いてなくない? @swift-5.1.5
var array = [5, 4, 3, 2, 1] var slice = array[1...3] slice.sort() array[1...3] = ArraySlice(Array(slice)) print(array)
(edited)
Avatar
swift51 BOT 31-Jan-20 09:35 AM
[5, 2, 3, 4, 1]
(edited)
Avatar
koher 31-Jan-20 09:35 AM
インデックスを 0 はじまりにリセットしてから subscript set しても同じ結果に。
Avatar
omochimetaru 31-Jan-20 09:36 AM
@swift-5.1.5
var array = [5, 4, 3, 2, 1] var slice = array[1...3] slice.sort() array[1...3] = slice print(array) // 5, 2, 3, 4, 1
Avatar
swift51 BOT 31-Jan-20 09:36 AM
[5, 2, 3, 4, 1]
Avatar
omochimetaru 31-Jan-20 09:36 AM
こうじゃないですか?
Avatar
koher 31-Jan-20 09:36 AM
うん、どちらでも同じ結果になるから
09:37
単純に array1...3 にコレクションを代入してるだけで
Avatar
omochimetaru 31-Jan-20 09:37 AM
同じArrayに対するSliceで操作しないと不正な気がする。
Avatar
koher 31-Jan-20 09:37 AM
ArraySlice のインデックスが 0 はじまりでないからできることの例になってない気がする。
Avatar
omochimetaru 31-Jan-20 09:38 AM
ああ、それはなってないですね。そもそもSliceに対するsubscriptを全くしていないので。
09:39
@swift-5.1.5
var array = [5, 4, 3, 2, 1] var slice = array[1...3] slice.sort() array[0...1] = slice print(array)
Avatar
swift51 BOT 31-Jan-20 09:39 AM
[2, 3, 4, 3, 2, 1]
Avatar
koher 31-Jan-20 09:39 AM
一瞬 subscript set されるときに ArraySlice 側のインデックスが利いてくるのかと思ったんよね。
Avatar
omochimetaru 31-Jan-20 09:40 AM
場所も幅も(!)変えられますね
Avatar
koher 31-Jan-20 09:40 AM
あー。それは SwiftImage の ImageSliceArraySlice を踏襲してたつもりだけど 2 次元では真似できないな・・・。 < 幅も変えられる (edited)
09:42
そもそも set がなかった・・・。サイズ違いは precondition してるのかと思ってたけど。
public subscript(xRange: Range<Int>, yRange: Range<Int>) -> ImageSlice<Pixel> { return ImageSlice(image: self, xRange: xRange, yRange: yRange) }
Avatar
koher 01-Feb-20 03:18 AM
同じ型であっても、同じ extension スコープからしかアクセスできないようなアクセス修飾子ほしくないですか? private より狭いやつ。 @swift-5.1.5
struct Foo {} extension Foo { private var a: Int { 42 } func f() { print(a) } // OK } extension Foo { func g() { print(a + 1) } // これを禁止したい } Foo().g()
Avatar
swift51 BOT 01-Feb-20 03:18 AM
43
Avatar
koher 01-Feb-20 03:20 AM
↑でいうと f のサブの処理を a に切り出すようなときに、 a が他から可視である必要がないので。ローカル関数でもいいんですけど、スコープがネストするし個人的に読みづらい気がするんですよね。
03:21
それに、その extension で共通に使われるけど他からは使われない関数とかだとローカル関数にできないし。
03:21
その extension をファイルを分けて private にするとかがいいんでしょうか。
Avatar
tarunon 01-Feb-20 06:48 AM
ファイル分けるのが良さそうな気はします
06:49
昔はprivateとfileprivateでその辺切り分けれた気がするんですけどね
Avatar
koher 01-Feb-20 01:35 PM
僕もそう思ったんですが、昔の private は今の fileprivate だったような気もしてきました・・・。
Avatar
Kishikawa Katsumi 01-Feb-20 03:13 PM
確認してみた。 @swiftbot --version=3.0.1
class Foo { private var fooPrivate = "private property" } extension Foo { func bar() -> String { return fooPrivate } } print(Foo().bar())
Avatar
swiftbot BOT 01-Feb-20 03:13 PM
Author icon
kishikawakatsumi
class Foo { private var fooPrivate = "private property" } extension Foo { func bar() -> String { return fooPrivate } } print(Foo().bar())
Version:
swift-5.1.3-RELEASE
Output:
private property
Error:
Avatar
Kishikawa Katsumi 01-Feb-20 03:13 PM
あれ、3で実行されない。。 (edited)
15:15
@swiftbot --version=3.0.1
class Foo { private var fooPrivate = "private property" } extension Foo { func bar() -> String { return fooPrivate } } print(Foo().bar())
Avatar
swiftbot BOT 01-Feb-20 03:15 PM
Author icon
kishikawakatsumi
class Foo { private var fooPrivate = "private property" } extension Foo { func bar() -> String { return fooPrivate } } print(Foo().bar())
Version:
swift-3.0.1-RELEASE
Output:
Error:
/usercode/main.swift:7:16: error: 'fooPrivate' is inaccessible due to 'private' protection level return fooPrivate ^ /usercode/main.swift:2:17: note: 'fooPrivate' declared here private var fooPrivate = "private property" ^
Avatar
koher 01-Feb-20 03:36 PM
あれ?↓の時点ではスコープ内のみで、その後同一の型の extension からもアクセスできるようになったんでしたっけ? https://github.com/apple/swift-evolution/blob/master/proposals/0025-scoped-access-level.md
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
15:36
なんかそんな Proposal あったような気がしてきました。
15:36
private: symbol visible within the current declaration
15:37
class A { private var counter = 0 // public API that hides the internal state func incrementCount() { ++counter } // hidden API, not visible outside of this lexical scope private func advanceCount(dx: Int) { counter += dx } // incrementTwice() is not visible here }
15:41
Existing code will need to rename private to fileprivate to achieve the same semantics,
15:42
なので、 Swift 2 では private は今の fileprivate で、その後レキシカルスコープまで狭められたけど、さらにその後同一の型の extension からは参照できるように修正された?
Avatar
Kishikawa Katsumi 01-Feb-20 04:10 PM
全く思い出せない。。。fileprivateもあんまり使わないからなあ。
16:11
今のfileprivateってあまり使いどころないような気がしている。。。
Avatar
koher 01-Feb-20 04:19 PM
僕はそのファイルローカルでしか使わない fileprivate な便利メソッドを extenion で既存の型に生やしたりします。 (edited)
Avatar
Kishikawa Katsumi 01-Feb-20 04:21 PM
privateでも同じじゃないです?
Avatar
koher 01-Feb-20 04:22 PM
private な API (メソッドやプロパティ)って同じファイル内でも別の型からは呼べなくないですか? (edited)
Avatar
Kishikawa Katsumi 01-Feb-20 04:24 PM
いや、できますよ。 こういうやつですよね?この例ではCGRect.integral() をImageResizerから呼んでいます。
import UIKit import AVFoundation public struct ImageResizer: ImageProcessing { ... } private extension CGRect { func integral(_ scale: CGFloat) -> CGRect { return CGRect(x: floor(origin.x * scale) / scale, y: floor(origin.y * scale) / scale, width: ceil(size.width * scale) / scale, height: ceil(size.height * scale) / scale) } }
Avatar
koher 01-Feb-20 04:24 PM
private extensionfileprivate になるとさっき調べていたときに見た気がします。
16:25
トップレベルの privatefileprivate だということだったと思います。
Avatar
Kishikawa Katsumi 01-Feb-20 04:26 PM
なのでfileprivate使わないなあ、と思いまして。あえてfileprivateじゃないと書けないことってあったっけ?と思って、そうすると、なんで変えたんだっけ?とわからなくなってきました。
16:28
internal/publicのスコープのプロパティやメソッドに対して細かくこれはprivate、こっちはfileprivateってやるユースケースがあるのかな。
Avatar
koher 01-Feb-20 04:30 PM
@swift-5.1.5
struct Foo { var value: Int } extension Foo { private var squareValue: Int { value * value } func f() { print(squareValue) } } struct Bar { var foo: Foo func g() { print(foo.squareValue + 1) } } Bar(foo: Foo(value: 42)).g()
Avatar
swift51 BOT 01-Feb-20 04:30 PM
exit status: 1 with stderr:
<stdin>:12:26: error: 'squareValue' is inaccessible due to 'private' protection level func g() { print(foo.squareValue + 1) } ^~~~~~~~~~~ <stdin>:6:17: note: 'squareValue' declared here private var squareValue: Int { value * value } ^
Avatar
koher 01-Feb-20 04:32 PM
↑のケースで squareValueprivatefileprivate にするか、 private extension Foo にしないといけないんですが、後者の場合 f のアクセスレベルにも影響があるので f を分離しないといけません。が、 fileprivate にしたいものだけ分離して private extension Foo のように書けば良いので fileprivate は要らないってことですか?
16:32
個人的には private extension Foo と書くよりも、個別に fileprivate を書いた方がわかりやすいような気がします。
Avatar
Kishikawa Katsumi 01-Feb-20 04:41 PM
いや、私があんまりそういう感じに書かないだけなので、
トップレベルの private は fileprivate
というのに慣れていて、そうするとfileprivateなんであるんだっけ?と感じただけです。 fileprivateはユニークで良いと思っています。 私も private == fileprivate として使ってるわけですし。
Avatar
koher 01-Feb-20 04:47 PM
private extension 方式で書いていると、本物の private と混同してしまったりはしませんか?しないからその方式なのかもしれませんが・・・。
16:48
まあ、トップレベルの private func とかは結局 fileprivate なんですよね。
Avatar
Kishikawa Katsumi 01-Feb-20 04:54 PM
private extension CGRect { ... }
^ こう書いて、ファイルないの他のTypeから使えるの、自然だと思ってたけど私が単にそれに慣れただけって気がしてきましたね。
16:55
つまり、
class Foo { ... // 同じ型なのでprivate extension Fooのメソッド・プロパティが呼べる } private extension Foo { ... }
^ これと
(edited)
16:55
class Foo { ... // fileprivate extension CGRectのメソッド・プロパティが呼べる } fileprivate extension CGRect { ... }
これを使い分ける方が一貫性がありそう、っていう話ですね?
(edited)
Avatar
koher 02-Feb-20 01:53 AM
そこまで強い意見があるわけではないんですが、
private extension Foo { func f() { ... } }
extension Foo { fileprivate func f() { ... } }
が同じになるのは、前者では字面上の private に引きづられて fileprivate ではなく private と勘違いしそうだなという感じです。僕が慣れてないだけかもしれませんが。
01:55
それとは直交する話として、同じ型であってもレキシカルスコープに限定する private がほしいなと思ったと。 scopeprivate みたいな感じか、今の privatetypeprivate みたいにするか。まあでも今でも複雑だし、 tarunon さんの言うようにファイル分けるが現実的そうですね。
Avatar
masakihori 06-Feb-20 12:56 AM
@swift-5.1.5
func f(_ array: [[Int]]) -> Int { array .filter { $0.count > 2 } .reduce([Int.min, Int.min]) { switch ($0, $1) { case let (max, new) where max[0] > new[0]: return max case let (max, new) where max[0] == new[0]: return max case let (max, new) where max[0] < new[0]: return new } }[1] } print(f([[0, 0], [0, 1], [0, 3]]))
Avatar
swift51 BOT 06-Feb-20 12:56 AM
exit status: 1 with stderr:
<stdin>:5:9: error: switch must be exhaustive switch ($0, $1) { ^ <stdin>:5:9: note: add missing case: '(_, _)' switch ($0, $1) { ^
Avatar
masakihori 06-Feb-20 12:56 AM
怒られる。なぜなのか
Avatar
omochimetaru 06-Feb-20 12:57 AM
whereは網羅チェッカーが対応してない
Avatar
masakihori 06-Feb-20 01:04 AM
そんなー。 頼りにしてるのに
Avatar
omochimetaru 06-Feb-20 01:05 AM
比較結果をenumで返す関数を自作してそれを経由するとか・・・
Avatar
masakihori 06-Feb-20 01:06 AM
まじめにユニットテスト書いたりですね
Avatar
norio_nomura 07-Feb-20 12:26 PM
Xcode 11.4 betaでSWIFT_CROSS_MODULE_OPTIMIZATION = YESとすると、-cross-module-optimizationが有効になる。
12:27
This is a first version of cross module optimization (CMO). The basic idea for CMO is to use the existing library evolution compiler features, but in an automated way. A new SIL module pass &qu...
Avatar
norio_nomura 08-Feb-20 12:29 AM
Xcode 11.4のSwiftに _forEachField() ってのが入ってる。 https://github.com/apple/swift/pull/29042
This function walks all the fields of a struct, class, or tuple type, and calls body with the name, offset, and type of each field. body can perform any required work or validation, returning true ...
Avatar
tarunon 08-Feb-20 01:33 AM
Mirrorから出来ること増えるだろうか
Avatar
omochimetaru 08-Feb-20 01:58 AM
masterだとマージされてないけど配布版に入ってるのか
01:58
SwiftUI Canvasとかで使ってるのかな
Avatar
tarunon 08-Feb-20 02:04 AM
offsetがあってフィールドの変更が可能なら、DynamicPropertyの実現に使えそうな気がする (edited)
02:04
Mirrorだと出来ないんだよね
Avatar
omochimetaru 08-Feb-20 02:06 AM
ポインターが来てるからできるんじゃない? (edited)
Avatar
tarunon 08-Feb-20 02:06 AM
できそうだよね。SwiftUIで使われてると思う
Avatar
tarunon 08-Feb-20 10:59 AM
激アツ
11:00
これはワクワクするな〜
Avatar
omochimetaru 08-Feb-20 11:01 AM
おー
Avatar
kateinoigakukun 08-Feb-20 11:01 AM
これどうなってるんだ
Avatar
tarunon 08-Feb-20 11:02 AM
_forEachFieldからフィールドへのオフセットと型を取り出して、structの先頭からのオフセットがフィールドの値なのでそこに新しい値をねじ込んでいます。 didSetも発生しているので
11:02
これがあるとSwiftUIが作れる。
Avatar
kateinoigakukun 08-Feb-20 11:04 AM
UnsafeMutablePointer経由でwriteしてもdidSetトリガーされるのどうやってるんだろう
Avatar
tarunon 08-Feb-20 11:04 AM
もともとUnsafeMutablePointerから書き込んでもdidSetは発火してた気がする
Avatar
omochimetaru 08-Feb-20 11:05 AM
それはないのでは
Avatar
tarunon 08-Feb-20 11:05 AM
あれれ
Avatar
omochimetaru 08-Feb-20 11:05 AM
withUnsafePointer関数が
11:05
inoutで受けてるから
Avatar
tarunon 08-Feb-20 11:05 AM
ああそうですね
11:05
えーとなので
Avatar
omochimetaru 08-Feb-20 11:05 AM
inoutに渡すと書きこみになるだけ
Avatar
tarunon 08-Feb-20 11:06 AM
各フィールドにdidSetつけても発火しない。
Avatar
kateinoigakukun 08-Feb-20 11:06 AM
あーそっか、なるほど
Avatar
tarunon 08-Feb-20 11:06 AM
mutable func updateAllDynamicProperties() 自体は十分に作れる素養はあるので (edited)
11:07
今書いてるコードで萎えてたのは全部解決しそうだ
Avatar
omochimetaru 10-Feb-20 06:43 AM
06:44
タプルもいけるんだねえ
06:45
nameがドット付きになってるのstructとは一貫性が無いな。
Avatar
omochimetaru 12-Feb-20 09:14 AM
Accept trailing closures in following form: foo { &lt;label-1&gt;: { ... } &lt;label-2&gt;: { ... } ... &lt;label-N&gt;: { ... } } Consider each labeled block to be ...
09:14
面白いマルチクロージャ記法をxedinさんが出してる
09:15
結局2重カッコになってるので
foo( label1: { }, label2: { } )
とあんまり辛さが変わってないと思うけど・・・ (trailing closureの嬉しさは末尾の }) の回避にあると思う)
09:16
でも、カンマは要らなくなるみたいだな。 なんかこれもSwiftUIのView記法をいい感じにしたくてやってそう。
Avatar
tarunon 12-Feb-20 09:36 AM
Buttonとか結構辛いですからね
Avatar
omochimetaru 12-Feb-20 06:15 PM
Swift currently supports a special syntax for a single trailing closure which makes it possible to pass a closure as function's final argument after parentheses as a block without a label. This is very useful when the closure expression is long. I propose to extend this func...
18:15
ピッチここにあった
Avatar
tarunon 12-Feb-20 06:16 PM
殊SwiftUIに関して言えば、FunctionBuilderを如何に差し込むかみたいなところがあるので
Avatar
omochimetaru 12-Feb-20 06:17 PM
I think the biggest advantage comes when these closure arguments grow in size especially in SwiftUI.
Avatar
tarunon 12-Feb-20 06:17 PM
この機能は欲しいだろうなぁという感じ
Avatar
omochimetaru 12-Feb-20 06:17 PM
xedinさん自分で書いてた
Avatar
tarunon 12-Feb-20 06:18 PM
FBによる型の拡張とORTのシナジーが凄いんだよな、よく出来てる
18:18
一方で複数closureが辛いかつ、表現が制限されるのも真なので
18:19
どっちにしてもFBの一般化に伴ってSwiftuI以外でも必要とされるだろうなという気はしている (edited)
Avatar
omochimetaru 12-Feb-20 06:19 PM
丸括弧で普通に書いたら何がダメなの?カンマ?
Avatar
tarunon 12-Feb-20 06:20 PM
複数closureならtrailing closureが禁止されるなら、それはアリ
18:21
例えば2カラムのUIにおいて2引数がleft: FB(略), right: FB(略)の時に、見た目が補完で勝手に崩されるのが一番キツい (edited)
Avatar
omochimetaru 12-Feb-20 06:21 PM
それって、Xcodeのフォーマッターが悪いのではないんかな
Avatar
tarunon 12-Feb-20 06:22 PM
trailing closureの言語機能というかデザイン自体が
18:23
ラベル省略する仕様でありながら複数closureでも使えちゃう、というのはそもそも宜しくないというのが根底にあると思う。フォーマッターはそれが出現しやすくしてるだけ。
18:23
確かにmap filter reduceを初め多くの関数が1closure引数なのはそうだとしても (edited)
Avatar
omochimetaru 12-Feb-20 06:23 PM
ああ、rightだけtrailingでズレるのはまあそうか
Avatar
tarunon 12-Feb-20 06:24 PM
2closure引数の時を考慮できていない言語デザインというのは真だと思う
Avatar
omochimetaru 12-Feb-20 06:24 PM
まあ確かに。
Avatar
tarunon 12-Feb-20 06:25 PM
だから保守的に行くなら禁止ならそれはそれでok
18:27
あー
18:28
ラベルがアンスコで利用側で省略される時だけtrailing可能ってのは、良い塩梅かもしれん (edited)
Avatar
omochimetaru 12-Feb-20 06:28 PM
あー
18:28
たしかにーーーー
Avatar
tarunon 12-Feb-20 06:29 PM
それはつまりclosureの用途が自明であることを指してるからね
Avatar
omochimetaru 12-Feb-20 06:30 PM
でもそれは、ソース互換性が無いね。オートマイグレーションはいけそうだが。
Avatar
tarunon 12-Feb-20 06:31 PM
ソース互換性は別にいらないっしょ、皆慣れてる
Avatar
omochimetaru 12-Feb-20 06:31 PM
いや、Swift4でなるべく保つ事になったような
18:31
で、5からはABI。
Avatar
tarunon 12-Feb-20 06:31 PM
手遅れか〜
18:31
まあでも再考して欲しいんだよな
Avatar
omochimetaru 12-Feb-20 06:32 PM
たまには破壊して欲しいなあ(懐古
Avatar
tarunon 12-Feb-20 06:45 PM
なんかだから、本質的には「multiple trailing closureをどうするか」じゃなくて、「ラベル付きtrailing closureをどうするか」その延長として複数がどうなるか、だと議論が綺麗になりそうな気がするのよな
18:45
まだ議論中なのかな?
18:47
実際 .first { ... } とか良い例で、初見だとナンジャコリャでしょ
18:47
where句なんだよ、わからんって
Avatar
omochimetaru 13-Feb-20 01:22 AM
議論中だよ
Avatar
Kishikawa Katsumi 13-Feb-20 03:35 AM
ソース互換性は細かいところでは結構壊れてる気もするけどな。いつの間にか直ってることもあるからリリースでは壊れてたことはないのかもしれないけど。
Avatar
omochimetaru 13-Feb-20 06:13 AM
Introduce support for initialized let/var declarations within function builder closures, e.g., let (a, b) = c() We generate constraints for the declarations as elsewhere, but the types of the decl...
06:13
FunctionBuilderでlet書けるのはとても良さそう。
Avatar
tarunon 13-Feb-20 06:23 AM
let書けるようにしたの、Optional Bindingやswitchの布石では!
Avatar
omochimetaru 13-Feb-20 06:26 AM
Hi all, We've been making quite a bit of progress on the implementation of function builders within the Swift compiler's type checker. While I'm not quite ready to reopen the big design discussion, I wanted to call attention to some of the work we're doing (some of which has ...
06:27
Douglasがここで方針予告してて
06:27
With this refactor, it becomes easy to support aspects of statements that cannot be described in expressions, such as multiple conditions in an if 11 and support for if #available 4. It's scaffolding for supporting let declarations, if let, and switch statements to make function builders more expressive, although that generalization is still a work-in-progress.
06:27
let、if let, switchって書いてるので、そのとおりだと思う。
06:28
布石としてデカイのがこのone-way constraint https://github.com/apple/swift/pull/25983
Introduce the notion of &quot;one-way&quot; binding constraints of the form $T0 one-way bind to $T1 which treats the type variables $T0 and $T1 as independent up until the point where $T...
Avatar
tarunon 13-Feb-20 06:37 AM
新しい推論の方法ですか
Avatar
omochimetaru 13-Feb-20 06:46 AM
うん
06:48
今までの型推論って制約式をかき集めてエイヤで全部の関係を解いてたのに対して
06:49
A <one-way bind> B は、Bが確定してからA := Bに変わるっていう壁として働くので
06:50
この文を解いたら次はこの文を解く みたいな前後関係が扱えるように成った
06:50
もともとSwiftは文ごとに推論してたから問題なかったんだけど
06:51
FunctionBuilderは複数の文の結果をbuildExpressionの引数として並べるから
06:51
通常のコードと違って複数の文をいっぺんに推論する必要がある
06:52
ので、「FBの複数の文を同時に推論する」必要と、 従来の「1文ずつ推論を進める」機構を、両立させる必要があって
06:53
推論機の内部で制約としてその「1区切りずつ進める」方法論を実現するのがone-way
14:16
azoyさんがリフレクションやろうとしてる
Avatar
niw 05-Mar-20 06:01 PM
あってなかったようなreflection
Avatar
omochimetaru 06-Mar-20 02:01 AM
ABI安定化したし、その上でSwiftUIもいろいろやってるし、キチンとしたやつが欲しいなーと思ってた
16:24
レス数も期日も伸びまくってたSE-0279スレがついに閉じた。
16:24
中盤でダグvsラトナーが伸びてたのがアツかった
Avatar
Kishikawa Katsumi 14-Mar-20 04:27 PM
結局決まらなかったのかしら?
Avatar
omochimetaru 14-Mar-20 04:27 PM
レビュースレッドがいったん閉じてから、後日アナウンスが別スレッドで投稿されるのがパターンです (edited)
Avatar
Kishikawa Katsumi 14-Mar-20 04:27 PM
なるほど〜
Avatar
omochimetaru 14-Mar-20 04:29 PM
これだけゴチャゴチャするときはreturn for revisionになる事が多いけど、 なんか圧を感じたので、説明付けてacceptになりそうで不安 (edited)
Avatar
koher 20-Mar-20 04:56 AM
ArraySlice<Element> にできて Slice<Array<Element>> にできないことってありますか?一見、 where Base.Index == Int とか色々付けて特殊化すればパフォーマンス含めて同じにできそうに思うんですが・・・。どうして typealias ArraySlice<Element> = Slice<Array<Element>> でないのかという疑問です。初期の Swift ではできなかったから?
Avatar
omochimetaru 20-Mar-20 04:58 AM
ArraySliceってArrayを持っているんじゃなくてArrayの中のストレージオブジェクトを持っているのに対して、 Slice<C> は C を持つんじゃないでしたっけ。
Avatar
koher 20-Mar-20 04:58 AM
なるほど、 C を持たずにバッファだけを持てば Array のがわの分だけ領域が節約できると。
Avatar
omochimetaru 20-Mar-20 04:59 AM
ガワの情報もそうだしメモリアクセスが一手減ったりするかも? CoWの都合で参照カウント2以上になってしまうケースが生じたりするかも別途気になる。 (edited)
Avatar
koher 20-Mar-20 05:01 AM
Arraystruct だからメモリアクセスの手数は変わらなくできないかな?
Avatar
omochimetaru 20-Mar-20 05:02 AM
最適化でそうなる可能性は期待できますね。
Avatar
koher 20-Mar-20 05:04 AM
ガワの分の削減だけでも意味ありそうだけど、そうすると Slice ってサボって楽するためのものでしかなくて、個別実装した方が実行効率は良くなるのか。
Avatar
omochimetaru 20-Mar-20 05:04 AM
一般的はそうな気がします。
05:04
Sliceはジェネリック実装で必ずしも理想コードになるとは限らない。
Avatar
koher 20-Mar-20 05:05 AM
SliceProtocol があって、デフォルト実装いっぱいついてて、バッファの部分だけ個別実装とかもありだったのかな。
Avatar
omochimetaru 20-Mar-20 05:06 AM
サボり用の Slice がある分には良さそう (edited)
Avatar
koher 20-Mar-20 05:07 AM
ArraySlice の方が効率良くて Slice はサボり用ということで納得しました。ありがとう🙏 (edited)
Avatar
omochimetaru 20-Mar-20 05:09 AM
あ、 AnyCollection だと Slice より良い実装が無い、とかあるかしら?
05:14
自分自身を使うみたい。
Avatar
omochimetaru 20-Mar-20 05:14 AM
なるほど。
Avatar
koher 20-Mar-20 05:15 AM
抽象実装が二重になるより確かに効率良さそう。
Avatar
koher 20-Mar-20 09:25 AM
Linux の URLSession ってまだ Alamofire が動かないくらいダメなの? https://forums.swift.org/t/alamofire-on-linux-possible-but-not-release-ready/34553
Due to the heroic efforts of @SlaunchaMan, there's a WIP PR up that gets Alamofire mostly working on Linux, including tests! However, it's not really in a releasable state, even if were were ready for it, due to a few issues around Foundation on Linux, namely: URLSessionTas...
Avatar
koher 25-Mar-20 12:10 AM
今更ながらだけど、 callAsFunctionsubscript との一貫性を考えたら subscript のように特殊構文が良かった気がする・・・。
struct Foo { invoke(a: Int, b: String) -> Bar { ... } }
みたいな。 subscriptgetForSubscriptingsetForSubscripting でないのと同じように。
(edited)
Avatar
Kishikawa Katsumi 25-Mar-20 12:17 AM
同意ですねえ
Avatar
koher 25-Mar-20 12:18 AM
Proposal の Alternative Considered にそれっぽい記述がないんですが、検討されなかったんですかね?
Avatar
t.ae 25-Mar-20 12:18 AM
最初それでreturned for revisionでしたからね
00:18
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
Avatar
koher 25-Mar-20 12:18 AM
そうなのか。
Avatar
t.ae 25-Mar-20 12:18 AM
そうここに書いてあります。
Avatar
koher 25-Mar-20 12:18 AM
ほんとだ。見落としてた。
Avatar
koher 25-Mar-20 12:27 AM
イマイチよくわからないけど↓この部分?
On the first two points, the core team debated several designs and came to recommend that we keep callable syntax directly aligned with func to keep the function grammar consistent and make naming clear. In particular, the core team recommends picking a standard name (like call or invoke) that can be used as a normal named member, and which is automatically callable with function invocation syntax. This would give us syntax like func call(). With this approach, you can invoke the callable with with either value() or value.call(), and can partially apply the callable with value.call.
https://forums.swift.org/t/returned-for-revision-se-0253-static-callables/23290
Hello Swift community, The review of SE-0253: Static callables ran from March 27... April 5, 2019. The core team is very positive about the idea of this feature, but would like to see some changes to the proposal, followed by another round of public review. As such, the prop...
00:28
let foo = value.callAsFunction ができるのがうれしい理由の一つ?
Avatar
t.ae 25-Mar-20 12:29 AM
それだけならFoo.init もあるし……という気がしますね。
00:30
initはフィールドの初期化という特殊な条件があるのに対してcallAsFunctionは普通のfuncと差がないとかそういうことを書いてる気がします。
00:31
we keep callable syntax directly aligned with func to keep the function grammar consistent
Avatar
koher 25-Mar-20 12:32 AM
subscript は?
00:32
callAsFunction って subscript と同種の存在だと思うんだけどなぁ。
00:33
[] で呼び出すか () で呼び出すか。
Avatar
t.ae 25-Mar-20 12:33 AM
subscriptはget/setあるからvarのほうが近いのかとも思えますが
Avatar
koher 25-Mar-20 12:33 AM
でも今や subscript はジェネリックだし・・・
00:33
throws はまだできないんだっけ?
Avatar
t.ae 25-Mar-20 12:33 AM
getに限ればcallAsFunctionと同じような話ですね
Avatar
koher 25-Mar-20 12:34 AM
@swift-5.2.5
struct Foo { subscript(i: Int) throws -> String { "XYZ" } }
(edited)
Avatar
swift52 BOT 25-Mar-20 12:34 AM
exit status: 1 with stderr:
<stdin>:2:23: error: expected '->' for subscript element type subscript(i: Int) throws -> String { "XYZ" } ^ <stdin>:2:23: error: expected subscripting element type subscript(i: Int) throws -> String { "XYZ" } ^ <stdin>:2:23: error: single argument function types require parentheses subscript(i: Int) throws -> String { "XYZ" } ^~~~~~ ( )
(edited)
Avatar
koher 25-Mar-20 12:35 AM
throws はまだできないのか。昔議論されたまま放置か。
Avatar
koher 25-Mar-20 12:43 AM
あと、 Swift 5.2 で導入された↓の二つ、バランスおかしくないですか?
// SE-0249 let getUserId1: (User) -> String = \.id // OK //print(\.id(user)) // NG print(user[keyPath: \.id]) // OK
// SE-0253 struct GetUserId { func callAsFunction(_ user: User) -> String { user.id } } let getUserId = GetUserId() //let getUserId2: (User) -> String = getUserId // NG let getUserId2: (User) -> String = getUserId.callAsFunction // OK print(getUserId(user)) // OK
00:44
KeyPath は関数型に暗黙変換できるけど value(...) の呼び出しはできない。 callAsFunction は関数型に暗黙変換できないけど value(...) の呼び出しはできる。
00:50
callAsFunction 、↓すらできないのか・・・。関数のように見えるけど関数として渡せないって辛くないのかな。
let ids: [String] = users.map(getUserId)
Avatar
t.ae 25-Mar-20 12:52 AM
//let getUserId2: (User) -> String = getUserId // NG
の時点で当然な気はしますね。
00:53
callAsFunction自体S4TFのLayer用途から来てて、一般的なケースはあんまり考えてないんじゃないかという印象
Avatar
koher 25-Mar-20 12:53 AM
そりゃそうなんだけど、特に KeyPath と比べるとバランス悪いなと。
00:53
Proposal には普通の関数だから .callAsFunction つければいいとか書いてあるけど。
00:54
もし callAsFunction が関数型に暗黙変換できるなら、 KeyPath も単に callAsFunction 付ければ良かっただけだと思うんよね。
Avatar
t.ae 25-Mar-20 12:55 AM
users.map(getUserId.callAsFunction) より users.map({ getUserId($0) }) が短い😂
Avatar
koher 25-Mar-20 12:55 AM
w
Avatar
t.ae 25-Mar-20 12:57 AM
keyPathの関数変換ってたしかmapとか高階関数で使いたいというモチベーションがあってやっと実装されたので、callAsFunctionもそういう需要があれば対応されるんじゃないでしょうか。
Avatar
koher 25-Mar-20 01:01 AM
うーん、やりたいとかそういうことじゃなくて、 () 呼び出しできないものが関数型に暗黙変換できて、 () 呼び出しできるものが関数型に暗黙変換できないって、バランスの取り方としてどうなんだと。
01:01
しかも、 Swift 5.2 で導入されるたった二つの言語仕様の追加なのに・・・。
Avatar
t.ae 25-Mar-20 01:02 AM
同時期に独立に導入されたので整合性については考慮されてないとかな可能性はありそうですね。
Avatar
rintaro 25-Mar-20 01:33 AM
let getUserId1: (User) -> String = \User.id // OK let getUserId2 = \.id as (User) -> String // OK let getUserId3 = \User.id as (User) -> String // NG
これはバグっぽいですね
Avatar
koher 25-Mar-20 01:35 AM
バグでしょうが何となくそうなっちゃった気持ちはわかりますねw (edited)
Avatar
koher 25-Mar-20 02:00 AM
callAsFunction 、無名 func にすれば良かったのでは。そうすれば新しいキーワードも要らないし、 func が関数ということとも一貫性があるし。
struct Foo { func(_ x: Int) -> Bar { ... } } let foo = Foo() foo(42)
(edited)
02:01
いや、それも検討されてたっぽいな。
How to spell a callable method: suggestions included things like call(), func call() , call func() , func() , func _ () , func function() , @callable func evaluate() {
Avatar
omochimetaru 25-Mar-20 02:43 AM
無名系は、初見殺し要素が増える シンプルな名前は既存のコードが思わぬ意味をもつ
02:44
って意見によって普通の関数定義かつcallAsFunctionになりました
Avatar
tarunon 25-Mar-20 02:45 AM
subscript(...) に対して function(...) にする、というのは個人的には好きだった
Avatar
omochimetaru 25-Mar-20 02:45 AM
subscriptには左辺値参照をもつvarのような機能があるから
02:45
callAsFunctionとは遠いと思います
02:47
引数をもったvarがsubscriptって感じですね inoutに渡すと書き戻される。
Avatar
tarunon 25-Mar-20 02:47 AM
そうではなく、コードの見た目の話
Avatar
omochimetaru 25-Mar-20 02:50 AM
どちらもキーワード定義により[]呼び出しと()呼び出しが実現できるようになって揃うって事ね。
Avatar
koher 25-Mar-20 02:53 AM
↓これは?やっぱり左辺値があるから func setForSubscripting は変って感じ?
subscript が getForSubscripting や setForSubscripting でないのと同じように。
Avatar
omochimetaru 25-Mar-20 02:53 AM
そうですね。 特殊な名前のメソッドにしちゃったら
Avatar
koher 25-Mar-20 02:53 AM
initstatic func initializeAsInstance でないのは?プロパティ初期化が特殊だから?
Avatar
omochimetaru 25-Mar-20 02:53 AM
inout書き戻しできる意味論が隠れる
02:56
initとstatic funcは、 initの中にはselfがあるのと
Avatar
koher 25-Mar-20 02:56 AM
特別な名前のメソッドに役割を与えるってのが Swift っぽくなくて気持ち悪い・・・
Avatar
omochimetaru 25-Mar-20 02:56 AM
required initに関わる継承関係の制約で、
02:56
static funcにはない型的な意味論がある気がしてる きちんと考え切れてないけど。 (edited)
02:57
ていうか、見えないallocとの絡みと言えばいいのかな allocの結果がselfとして渡ってくる
Avatar
koher 25-Mar-20 02:58 AM
無名 func 良かったと思うんだけどなぁ。キーワードかぶることもないし、これまでのコードを殺すこともないし。初見殺しより特定のメソッド名に役割を与える方が微妙な気が。
Avatar
omochimetaru 25-Mar-20 02:58 AM
callAsFunctionは呼び出しが無名な事以外は実装する側の特別な型ルールがない
02:58
検索性も議論されてましたね
02:59
callAsFunctionなら、なにこれ?からググって答えに行きやすい
02:59
個人的には名前がダサいしfunc call派でした 既存コードも多分同じ意味になってるだろう
Avatar
koher 25-Mar-20 03:00 AM
まあ、それはもうどうしようもないとして、 KeyPath との変換の整合性はどう思う?
Avatar
omochimetaru 25-Mar-20 03:00 AM
それだけ見て特別な事が起きるってわからない問題はありますね もし無名ならそういうヒントは付くのが良い
Avatar
koher 25-Mar-20 03:01 AM
Swift 5.2 で KeyPath は関数型に暗黙型変換できるようになったけど、 () 呼び出しはできない。 callAsFunction が付いてる型は () 呼び出しできるけど関数型に暗黙変換できない。
03:02
関数っぽいものが暗黙型変換できなくて、関数っぽくないものが変換できるのが微妙な気が。
03:02
しかも、その二つだけが同時に導入されるので目立つ。
Avatar
omochimetaru 25-Mar-20 03:11 AM
まずkeypathに関しては、関数形式で呼び出せないのは変な気はしているんですけど
03:12
subscript での [keyPath: keyPath] 形式は、さっきと同じで、左辺値の概念が入ってるんで、
03:12
そこは良いような気もしてます
03:12
callAsFunctionに関しては、おかしいと思ってるんですけど、多分まだ途中だからだと思っていて
03:12
callAsFunctionのその先の発展として、
03:12
関数型プロトコルの追加というのがあるはずで、
03:13
やるならそのタイミングなのかなと思ってます
03:14
とりあえずTensorFlowチームがモデルのコードの見た目だけでも通したくて、今のスコープでproposalが切られたと勝手に思ってます。
Avatar
koher 25-Mar-20 11:42 AM
もし callAsFunction が暗黙的変換されるようになったら、 SE-0249 で色々がんばらなくても KeyPathcallAsFunction 付けたらそれで済むと思うんだけど、それだと key path 式に限らず KeyPath 全般が変換できるようになるのと、 KeyPath() でコールできるようになるのでまずいかな?
11:46
subscript での [keyPath: keyPath] 形式は、さっきと同じで、左辺値の概念が入ってるんで、 そこは良いような気もしてます
一瞬なるほどと思ったけど、 foo[keyPath: \.bar]\.bar(foo) は主従が逆だからいいんじゃないかな? callAsFunction を持つのは KeyPath 側、 subscript(keyPath:) を持つのは Foo 側。
Avatar
omochimetaru 25-Mar-20 12:17 PM
ふ〜む KeyPathも関数オブジェクトとするのか、理にかなってるような気もします。
12:18
KeyPathはあんまり使ったことがなくて見落としてる事がないか自信が無いですが。
Avatar
omochimetaru 03-Apr-20 02:41 AM
C++ Exception Interop のスレで、C++の関数は無修飾だと例外を投げうるから、 これを全部throwsでインポートすると辛いので、 新たにthrows! という概念を追加して、 try できるけど何も書かない場合は try! 扱い というのはどうか、という話題が発生して、 そこにクリスラトナーが、 足し算のオーバーフローや配列の範囲外アクセスを throws! であることにすれば、 エラーハンドリングできるようになる って意見を書いている https://forums.swift.org/t/handling-c-exceptions/34823/38?u=omochimetaru
Yes, this seems reasonable to me. To reiterate other people's points and respond to Jon's comments upthread - I agree about the potential for abuse and agree that former Java programmers who haven't learned enough Swift may reach for throws! when they shouldn't - just like th...
👀 4
Avatar
tarunon 03-Apr-20 02:42 AM
ほー
02:43
logic failureがthrows!に成り得るのかな。fatalErrorとの兼ね合いも気になる
Avatar
omochimetaru 03-Apr-20 02:43 AM
IUOが ! が常に付いてる Optional であるのと同じノリで、 throws! な func は デフォルトで try! が付いてる(ただしはがせる) みたいな感じっすな
02:44
fatalErrorも throws! にできるね、プロセス即死を廃止できる。
02:45
あと話題としては、この throws! でのインポートは、 Python interop にもあったら便利だった、というのもある。
Avatar
koher 03-Apr-20 06:07 AM
func fatalError(...) throws! -> Never
とか?
Avatar
omochimetaru 03-Apr-20 06:09 AM
シグネチャはそうなりますね。
Avatar
koher 03-Apr-20 06:10 AM
preconsition とか assert は最適化でエラー投げたり投げなかったりになるけどいいのか?と思ったけど、別にシグネチャ的には問題なさそう。
06:12
interop で ! が氾濫するの、 Obj-C のときもそうだったけど、仕方ないとはいえ辛みがあるなぁ。 Obj-C は大分解消されてきたのに。
06:13
Python は動的型付けだからどうしようもないけど。
Avatar
omochimetaru 03-Apr-20 06:13 AM
interopされたシグネチャがthrows!に見えるだけでSwiftユーザーは書けないっていう意見もありますね。
06:13
KotlinのPlatform Type的な。
Avatar
koher 03-Apr-20 06:13 AM
Kotlin のFoo!
Avatar
omochimetaru 03-Apr-20 06:14 AM
まあthrows!をSwiftで書けるようにする話題はスレ違いってことで止められちゃったけど。
Avatar
koher 03-Apr-20 06:16 AM
Swift Concurrency Manifesto. GitHub Gist: instantly share code, notes, and snippets.
Avatar
omochimetaru 03-Apr-20 06:18 AM
ふむ
Avatar
koher 16-Apr-20 08:21 AM
Combine の foo.eraseToAnyPublisher() って AnyPublisher(foo) するのと何か違うんでしょうか?
08:21
@omochimetaru combine チャネルあってもいいかも?
Avatar
omochimetaru 16-Apr-20 08:22 AM
作りました
🙏 1
Avatar
norio_nomura 17-Apr-20 05:59 AM
ここのボットでswift -frontend -replとかしてたまに使うintegrated REPLをswiftから削除するにあたり、使ってる人がいるかどうか調査するスレッドが出来てたので、コメントしておいた。 https://forums.swift.org/t/rfc-removing-the-integrated-repl/35441/4
Hi, I sometimes use integrated REPL explicitly as swift -frontend -repl because it works in a docker container launched without the --privileged option. If integrated REPL is removed, it would be nice if LLDB REPL could be invoked in a docker container without the --privileg...
👍 2
Avatar
koher 24-Apr-20 02:42 AM
@swift-5.1.5 @swift-5.2.5
enum Foo { case a(Int, String) } switch Foo.a(42, "XYZ") { case .a(let x): print("\(x.0), \(x.1)") }
(edited)
Avatar
swift52 BOT 24-Apr-20 02:42 AM
42, XYZ
stderr:
<stdin>:6:9: warning: cannot match several associated values at once, implicitly tupling the associated values and trying to match that instead case .a(let x): ^
(edited)
Avatar
swift51 BOT 24-Apr-20 02:43 AM
42, XYZ
Avatar
koher 24-Apr-20 02:44 AM
これが今でもできると思ってなかった。 5.2 で warning になったのか。
Avatar
koher 06-May-20 03:05 PM
@swift-5.3.3
print([true, true, true].allSatisfy()) print([true, false, true].allSatisfy())
Avatar
swift53 BOT 06-May-20 03:05 PM
exit status: 1 with stderr:
<stdin>:1:37: error: missing argument for parameter #1 in call print([true, true, true].allSatisfy()) ^ <#(Bool) throws -> Bool#> Swift.Sequence:3:28: note: 'allSatisfy' declared here @inlinable public func allSatisfy(_ predicate: (Self.Element) throws -> Bool) rethrows -> Bool ^ <stdin>:2:38: error: missing argument for parameter #1 in call print([true, false, true].allSatisfy()) ^ <#(Bool) throws -> Bool#> Swift.Sequence:3:28: note: 'allSatisfy' declared here @inlinable public func allSatisfy(_ predicate: (Self.Element) throws -> Bool) rethrows -> Bool ^
Avatar
koher 06-May-20 03:05 PM
@swift-5.3.3
extension Sequence where Element == Bool { func allSatisfy() -> Bool { return allSatisfy { $0 } } } print([true, true, true].allSatisfy()) print([true, false, true].allSatisfy())
Avatar
swift53 BOT 06-May-20 03:05 PM
true false
Avatar
koher 06-May-20 03:05 PM
これってなんでないんでしたっけ?
15:06
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
Avatar
rintaro 16-May-20 01:01 AM
5.3 で Implemented になってた RangeSet https://github.com/apple/swift-evolution/blob/master/proposals/0270-rangeset-and-collection-operations.md が revert された。
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
01:02
Don’t push RangeSet into 5.3 since the additions are all available via the preview package. This will give it more time to bake. rdar://problem/63285386
👀 1
Avatar
omochimetaru 16-May-20 05:06 AM
まだPreviewPackageで提供するのか。 それを経てacceptしたんじゃないのか・・・ まあまだみんなそんなに使ってないしってことかなあ
Avatar
koher 16-May-20 05:19 AM
This will give it more time to bake.
なので、まだ不安があるということなのかな?
Avatar
omochimetaru 17-May-20 01:19 AM
The core team has asked that discussion be spawned in a separate thread regarding support for use of an optional label for the first trailing closure. Therefore, later today, I'll be sharing a draft proposal here which addresses that topic. While it has been brought to mind b...
01:20
単一末尾クロージャと、複数末尾クロージャの一つ目のクロージャに、ラベルをつける記法を導入する提案
01:20
これめちゃくちゃ良いと思う
Avatar
tarunon 17-May-20 01:21 AM
よさそう
Avatar
omochimetaru 17-May-20 01:21 AM
なぜなら、複数末尾クロージャが導入されたせいで、「末尾の最初のクロージャはラベルが無くてもわかりやすい関数名にする」っていう新しい命名指針が生まれちゃったのが、気持ち悪かったから。 この記法があれば、ラベルが消えることを気にした命名がいらない
Avatar
niw 17-May-20 01:22 AM
(,) がなくなるだけ、と。
Avatar
omochimetaru 17-May-20 01:27 AM
そうですね。右端の閉じかっこが移動して、通り過ぎたカンマが消えるだけになりますね
Avatar
niw 17-May-20 04:15 AM
func呼び出しにそもそも()なければよかったのでは...
04:15
print a
04:15
とかできる感じで
Avatar
omochimetaru 17-May-20 04:16 AM
objectiveCの[]が無い状態がそんなんですね
04:16
丸括弧無いとC系と違いすぎて流行らなかったのではないか
Avatar
niw 17-May-20 04:17 AM
まあそれはわかる気がする
Avatar
omochimetaru 17-May-20 04:18 AM
そのスタイルだとrubyが似てるけど
04:19
関数呼び出しのオペランドと、二項演算子の組み合わせが
04:19
文法的に見た目が曖昧でわかりにくそう
04:19
f a + b
Avatar
niw 17-May-20 04:20 AM
rubyはパーサーが凄いから...
Avatar
omochimetaru 17-May-20 04:21 AM
パーサーがすごくても人間が慣れるハードルはあるから。
04:23
(f a) + b なのか f(a + b)なのか。
Avatar
niw 17-May-20 04:35 AM
人間もすごくなれる! kwargsとか...
Avatar
omochimetaru 19-May-20 04:27 PM
I read these kind of things very frequent in the last couple weeks. That makes me wonder, what kind of breaking changes are considered/allowed in Swift 6? There are a couple other things that come to my mind that would require a breaking change to be really fixed / work.
16:28
あるスレでJoeGroffが「Swift6で破壊的変更する?」みたいな事言ったのを受けてアツいスレが立ってる
Avatar
niw 19-May-20 04:29 PM
break things move fast.
Avatar
omochimetaru 19-May-20 04:30 PM
破壊的な事は早く進む?
Avatar
niw 19-May-20 04:31 PM
Move fast and break things may refer to: Move fast and break things (motto), internal motto used by Facebook until 2014 Move Fast and Break Things (book), 2017 book by Jonathan Taplin subtitled How Facebook, Google and Amazon Have Cornered Culture and Undermined Democracy
16:31
逆だった
Avatar
tarunon 19-May-20 04:32 PM
激アツでワロタ
Avatar
omochimetaru 19-May-20 04:32 PM
なんか元の発言はだいぶ細かい話なんだけどw
16:33
resilent buildでない状況でも後から追加できる@extensible enumができたらいいよねみたいなスレ。
16:34
Move Fast and Break Things: How Facebook, Google, and Amazon Cornered Culture and Undermined Democracy
本のタイトルなのか。
(edited)
16:34
>>2 から結構過激なんだよな
Removing inout-to-pointer conversions would be great.
16:35
Slava_Perstov
I don't claim to speak for the core team, but my personal opinion is that we should consider a potential small number of changes to fix quirks in the language that are actively harmful in practice, or make the language harder to learn
16:36
Slavaが「コアチーム見解ではないが個人的には言語の実戦でよくハマる問題や言語を学びにくくしてる事は少しの修正をすることを考えて良いと思ってる」てきな事書いてる! (edited)
16:37
Examples would be cleaning up some of the implicit conversions in the type checker
16:37
some of the implicit conversionsに Optional wrapping は入りますか
Avatar
tarunon 19-May-20 04:37 PM
いれてくれ!!!w
16:38
ObjC互換という壁があるので精算はできないと思うけど
16:39
some of the implicit conversionsにOptional誰も突っ込んでないのな(´・_・`)
Avatar
omochimetaru 19-May-20 04:39 PM
今眺めてるけど誰も書いてなさそうw
16:39
if let 構文 直せないかな・・・
Avatar
koher 19-May-20 04:45 PM
John_McCall The Core Team has no interest in pursuing changes that would massively invalidate existing code.
https://forums.swift.org/t/breaking-changes-in-swift-6/35928/14
Avatar
omochimetaru 19-May-20 04:46 PM
massively invalidate existing code
ですよね
Avatar
koher 19-May-20 04:47 PM
massively はどの程度なんだろう?
Avatar
omochimetaru 19-May-20 04:49 PM
10%のコードの修正が必要ならmassivelyと感じるな
16:49
現実的には影響範囲1%ぐらいまでしか許されなさそう
Avatar
koher 19-May-20 04:50 PM
if let 直したら半分くらいのコードはビルドできなくなりそう😢
Avatar
omochimetaru 19-May-20 04:50 PM
半分じゃ済まないでしょうw
Avatar
niw 19-May-20 04:50 PM
0%と1%は大きな違いだけど
16:50
1%と10%はたいしたことないと思うんだよね
16:50
だからぶっ壊すなら壊せばいいと思う派
Avatar
omochimetaru 19-May-20 04:50 PM
なるほど?
Avatar
niw 19-May-20 04:50 PM
all or nothingだと思う
16:51
1% だから手で直せる〜
16:51
かどうかはコードの規模による
Avatar
koher 19-May-20 04:51 PM
0.1%くらいが想定されてそうな気も?
Avatar
niw 19-May-20 04:51 PM
0.1% だろうか 1% だろうが 10% だろうが、結局は相対的なものなので、同じことかなあって。 (edited)
Avatar
koher 19-May-20 04:52 PM
連続的ならそうですが、0.1%くらいになると個々人の体験では0%になる人が多そうなので、そのあたりは結構違いそうに思います。
16:52
10%と20%なら同じだと思いますが・・・。
Avatar
niw 19-May-20 04:53 PM
ああ、そうか、マイナーな機能かどうかという意味ではありうるかな
16:53
まあでもどうだろうね。
16:53
swiftは壊れ続きてきた過去があって
16:53
今もあるから
16:54
ちょっとくらい壊れてもなんとも思わないというバイアスが利用者にあると思う
Avatar
omochimetaru 19-May-20 04:54 PM
ww
Avatar
niw 19-May-20 04:54 PM
すくなくとも自分は if let かわっても文句言わない
Avatar
omochimetaru 19-May-20 04:54 PM
新社会人と話すと、落ち着いたここ2年ぐらいから触ってる人も結構居ますよ
Avatar
niw 19-May-20 04:55 PM
そっかー。
16:55
python2を知らない世代
Avatar
omochimetaru 19-May-20 04:55 PM
「Swift 1, 2, 3 の地獄を見てきた者たちだ、面構えが違う」のやつ (edited)
Avatar
niw 19-May-20 04:55 PM
ruby1.8を知らない世代
Avatar
omochimetaru 19-May-20 04:55 PM
意外とafter4世代が居る。
Avatar
niw 19-May-20 04:56 PM
まあ、破壊的変更に完璧に自動で書き換えられればなんの問題もないと思うな。
Avatar
koher 19-May-20 04:56 PM
Swift 2 → 3 は massive だけど、 Swift 4 → 5 だと修正なしで通ったコードベースも多そうな気も。巨大なアプリは無理かもだけど、そこそこの大きさまでのライブラリとか。
Avatar
omochimetaru 19-May-20 04:56 PM
python2は実際現行なので知らない世代まだいないかもw
😩 1
16:56
auto migrateできればいいのでは説は僕もある
Avatar
niw 19-May-20 04:57 PM
$ /usr/bin/python --version Python 2.7.16
16:57
辛い現実
Avatar
koher 19-May-20 04:57 PM
論点違うけど、 if let foo =if case let foo? = があるけどダメ?
Avatar
omochimetaru 19-May-20 04:57 PM
そのcaseの省略って事になってほしい
Avatar
koher 19-May-20 04:58 PM
case 省略したい気持ちはすごくわかる。 switchcase もだるい・・・。
16:58
パターンマッチの気持ちよさを削がれる・・・。
Avatar
omochimetaru 19-May-20 04:58 PM
確かにswitchcase めっちゃ書いてるな
Avatar
niw 19-May-20 04:59 PM
パタンマッチがうぬぬって感じなのはSwiftの残念な部分
16:59
スパーンって感じがない
16:59
unapply 欲しい
Avatar
koher 19-May-20 04:59 PM
AtCoderでRustを使う一億個の理由のうちの一つがこれ
Likes
482
17:00
こういう気持ちよさがない。まあ、文指向の Swift ではこれできないけど。
Avatar
niw 19-May-20 05:00 PM
インデントの色付けに目がいった
Avatar
koher 19-May-20 05:02 PM
確かに色付いてますね。色つけるなら (){} と色合わせてほしい気も? (edited)
Avatar
omochimetaru 19-May-20 05:04 PM
ゲーミングカラーリングってあんのかな 7色がアニメーションし続けて欲しい
Avatar
niw 19-May-20 05:05 PM
wwww
17:05
インデントの場所に応じてキーボードの色も変わると
17:05
便利かも
Avatar
omochimetaru 19-May-20 05:05 PM
かっこいい
Avatar
koher 22-May-20 01:29 AM
最近仕事でコード書いてて struct のプロパティで let 使った方が良さそうな新しい(?)パターンを発見した。 (参考) https://qiita.com/omochimetaru/items/7265e440418b38088ccb (edited)
記事について この記事は potatotips#39 という勉強会で発表した内容を再掲したものです。スライドの画像と、喋った言葉を載せました。 以下スライド それではこれから、Swift の struct の st...
01:30
たとえば、 Identifiable みたいなやつで、 id をキーにした Dictionary を作った場合、 id か書き換えられるとキーと整合性が取れなくなる。
01:31
まあでもこれは何にでも言えるので Dictionary の使い方の問題の範疇かな?
01:31
id の場合はキーとして使われやすいのでそういうケースが起こりやすいという違いはあるけど。
Avatar
lovee 22-May-20 01:31 AM
私も基本、イニシャライザーを通して欲しいstructはletでプロパティー宣言していますね
Avatar
koher 22-May-20 01:33 AM
↑は、それで本質的に防げてることはないという意見だったかと思います。
01:36
@swift-5.2.5
struct Foo: Identifiable { typealias ID = Int var id: ID var value: String } let foos: [Foo] = [ .init(id: 1, value: "ABC"), .init(id: 2, value: "XYZ"), ] var idToFoo: [Foo.ID: Foo] = .init(uniqueKeysWithValues: foos.map { ($0.id, $0) }) print(idToFoo) idToFoo[1]?.id = 999 print(idToFoo)
Avatar
swift52 BOT 22-May-20 01:36 AM
[1: main.Foo(id: 1, value: "ABC"), 2: main.Foo(id: 2, value: "XYZ")] [1: main.Foo(id: 999, value: "ABC"), 2: main.Foo(id: 2, value: "XYZ")]
Avatar
koher 22-May-20 01:39 AM
↑で 1 で引ける Fooid999 になってしまっているのが、 idlet なら防げる。他のプロパティでも同じことだけど、 id はキーとなることが想定されているものだから(そのために Hashable が強制されてるわけだし)、 let の方が望ましそう。
Avatar
lovee 22-May-20 01:43 AM
はい、私が言いたかったのも、このような場合私は idvaluelet 宣言しますね
struct Foo: Identifiable { typealias ID = Int let id: ID let value: String }
Avatar
koher 22-May-20 01:44 AM
↑の登校にはそこまで書かれてませんでした・・・。僕がおもちと話す中で感じてたことかも?
01:47
たとえば、 idlet にしても↓はできてしまうみたいな話ですね。
struct Foo: Identifiable { let id: Int var value: String } struct Bar { var foo: Foo } var bar = Bar(foo: Foo(id: 1, value: "ABC")) //bar.foo.id = 999 // NG bar.foo = Foo(id: 999, value: bar.foo.value) // OK
01:49
同じインスタンスを変更したのか、新しいインスタンスに差し替えたのかは、共有されていなければ区別できない。
投稿のこのあたりの意見に通づることかと。
01:52
var が適切でない既知パターンとしては複数のプロパティが連動しているケースで片方だけ変更された場合に困るということがありましたが( didSet 等で辻褄を合わせるか、変更を禁止するか)、 id はキーとしての利用が想定されているので Dictionary に入れた後で変更されると困るというのは新しいパターンかなと。
Avatar
kateinoigakukun 22-May-20 01:58 AM
「Nominalなタプル」ではない場合においては、letの意味があると思います。
https://twitter.com/omochimetaru/status/1127854216569995264?s=20 まさにこれですね。
@kateinoigakukun はい、プロパティの範囲や、複数のプロパティ間の関係を制約している場合や、キャッシュになるプロパティを持っているなど、「Nominalなタプル」ではない場合においては、letの意味があると思います。
♥️ 1
💯 1
Avatar
omochimetaru 22-May-20 03:36 PM
よくそんなむかしのリプライでてきたね
😋 1
Avatar
masakihori 10-Jun-20 07:50 AM
Swift.Setなんですけど、この動作ってどうなんでしょう? 普通に考えると、すべてのインスタンスのhashValueは同じで且つEqutableでもないので追加されるelementは1つだけだと思うんですけど、そうならないんですよね。 しかもなぜか勝手にvalueが同一のものを同じものと認識していますし。 これって便利だけどバグなのでは? (edited)
Avatar
swift52 BOT 10-Jun-20 07:51 AM
0 4157596543199416033 1 4157596543199416033 2 4157596543199416033 3 4157596543199416033 4 4157596543199416033 5 4157596543199416033 6 4157596543199416033 7 4157596543199416033 8 4157596543199416033 9 4157596543199416033
(edited)
Avatar
masakihori 10-Jun-20 07:51 AM
@swift-5.2.5
struct A: Hashable, CustomStringConvertible { let value: Int var description: String { value.description } func hash(into hasher: inout Hasher) { hasher.combine(0) // ハッシュは常にコンフリクトする } } let set1 = Set((0..<10).map(A.init)) let set2 = Set((0..<10).map(A.init)) set1.union(set2) .forEach { print($0, $0.hashValue) }
(edited)
Avatar
koher 10-Jun-20 07:53 AM
HashableEquatable ですね。
07:53
なので、ハッシュは衝突しているけど同一ではないので別の要素として追加されてると思います。
Avatar
masakihori 10-Jun-20 07:54 AM
勘違いでした!
07:55
objcの逆だった
Avatar
niw 10-Jun-20 09:48 PM
CVarArg めっちゃくわしいひといますか?
21:48
extension Optional : CVarArg { } がなぜ動くのか知りたい...
🤔 1
21:49
_ObjectiveCBridgeable が関係してそうなんだけど。
21:52
@swift-5.2.5
import Foundation extension Optional: CVarArg { } struct S { } let a: Any? = S() let s = String(format: "%@", a) print(s)
Avatar
swift52 BOT 10-Jun-20 09:52 PM
exit status: 1 with stderr:
<stdin>:2:1: error: type 'Optional<Wrapped>' does not conform to protocol 'CVarArg' extension Optional: CVarArg { ^ Swift.CVarArg:2:9: note: protocol requires property '_cVarArgEncoding' with type '[Int]' var _cVarArgEncoding: [Int] { get } ^ <stdin>:10:15: error: incorrect argument labels in call (have 'format:_:', expected 'repeating:count:') let s = String(format: "%@", a) ^~~~~~~ repeating count: <stdin>:10:30: error: cannot convert value of type 'Any?' to expected argument type 'Int' let s = String(format: "%@", a) ^ as! Int
Avatar
niw 10-Jun-20 09:52 PM
あれっ..
Avatar
Kishikawa Katsumi 10-Jun-20 09:53 PM
Macじゃないとダメそうっすね
Avatar
niw 10-Jun-20 09:53 PM
Foundation.framework あるなしの違い... (edited)
21:54
えー、じゃあなにか Foundation.framework に魔法があるのか
21:55
// protocol witness for CVarArg._cVarArgEncoding.getter in conformance A? sil shared [transparent] [serialized] [thunk] @$sxSgs7CVarArg4mainsABP05_cVarB8EncodingSaySiGvgTW : $@convention(witness_method: CVarArg) <τ_0_0> (@in_guaranteed Optional<τ_0_0>) -> @owned Array<Int> { // %0 // user: %2 bb0(%0 : $*Optional<τ_0_0>): // function_ref CVarArg<>._cVarArgEncoding.getter %1 = function_ref @$ss7CVarArgP10Foundations21_ObjectiveCBridgeableRzrlE05_cVarB8EncodingSaySiGvg : $@convention(method) <τ_0_0 where τ_0_0 : CVarArg, τ_0_0 : _ObjectiveCBridgeable> (@in_guaranteed τ_0_0) -> @owned Array<Int> // user: %2 %2 = apply %1<τ_0_0?>(%0) : $@convention(method) <τ_0_0 where τ_0_0 : CVarArg, τ_0_0 : _ObjectiveCBridgeable> (@in_guaranteed τ_0_0) -> @owned Array<Int> // user: %3 return %2 : $Array<Int> // id: %3 } // end sil function '$sxSgs7CVarArg4mainsABP05_cVarB8EncodingSaySiGvgTW'
21:55
SIL
Avatar
omochimetaru 10-Jun-20 09:56 PM
Foundationがあれば、SwiftのAnyはobjcのidにブリッジできるんじゃないかしら
Avatar
niw 10-Jun-20 09:56 PM
なるほど?
21:58
CVarArgstruct とか Optional<T> が動かなくてひじょうにしんどいのになんかこれは動くしなんやねん
21:58
って。
21:58
os_log とかで不便すぎる
21:58
(てかloggingみんなどうしてるの...)
Avatar
Kishikawa Katsumi 10-Jun-20 10:00 PM
os_logに与えるパラメータはとりあえず "\(foo)" ってしてます。
Avatar
omochimetaru 10-Jun-20 10:01 PM
一度Anyに入れるとObjCに渡せるのはNSDictionaryのAPI周りでよくある
Avatar
niw 10-Jun-20 10:02 PM
@Kishikawa Katsumi それだとos_logの機能まったくアレですよね...
22:02
{private} とか。
Avatar
omochimetaru 10-Jun-20 10:02 PM
NSDictionaryがDictionary<AnyHashable, Any>だから。
Avatar
niw 10-Jun-20 10:02 PM
AnyCVarArgじゃないので
Avatar
omochimetaru 10-Jun-20 10:03 PM
僕も岸川さんと同じでSwiftで文字列化してます
Avatar
niw 10-Jun-20 10:03 PM
このハックをするとAny? にすればなんでもいけるようになる
22:03
ふむむ
Avatar
Kishikawa Katsumi 10-Jun-20 10:04 PM
"{private}%s %s", "\(foo)", "\(bar)" ちょっとうろ覚えですけどこんな感じっすね。左側は必要に応じてマスクできるようにしておいて、右辺(というのか?)はStringにしちゃう。 (edited)
Avatar
niw 10-Jun-20 10:04 PM
なるほど
22:05
"\()" かあ...
22:05
きもい
Avatar
omochimetaru 10-Jun-20 10:06 PM
“\(foo)”は型検査もクソもないから僕も嫌いだけど楽だから使っちゃってる (edited)
Avatar
niw 10-Jun-20 10:07 PM
まあしょうがないのかなあ...
22:07
Foundation.framework ない状況ないから、Any == id の世界がいい...
Avatar
omochimetaru 10-Jun-20 10:08 PM
Linuxだと無さそう?
22:08
FoundationはあるけどObjCがない
Avatar
niw 10-Jun-20 10:08 PM
LinuxにはUIViewなんてないから
22:09
そんな環境はしらない的な
Avatar
omochimetaru 10-Jun-20 10:09 PM
oslogもないのかな
Avatar
niw 10-Jun-20 10:09 PM
os_logもないんじゃないかなあ
Avatar
omochimetaru 10-Jun-20 10:09 PM
そういえばSSSWGがLoggingのライブラリ出してたな。
Avatar
Kishikawa Katsumi 10-Jun-20 10:13 PM
SwiftLogはインターフェースで実装は結局os_logや他の仕組みを使う必要があるんですよね。
Avatar
omochimetaru 10-Jun-20 10:14 PM
てことは
22:14
書式転送もしてるのかな
22:14
無さそうな気がするな・・・
Avatar
niw 10-Jun-20 10:15 PM
ふむー
Avatar
Kishikawa Katsumi 10-Jun-20 10:16 PM
どうなんでしょう。それだったらOSLog直接でいいんじゃないか、と思って結局使ったことなくて、実際は便利なのかも。
Avatar
niw 10-Jun-20 10:18 PM
loggingはなんかもうちょっとswiftレベルできれいになって欲しいきもち
22:19
(あるいはきれいにできるなにかを提供)
Avatar
omochimetaru 10-Jun-20 10:19 PM
さっき出てきた{private}はどんな機能なんですか?
Avatar
niw 10-Jun-20 10:19 PM
%{private}d
22:19
とかやると、ロギングするときにその値がproductionではログされなくなります
22:19
パスワードとかそう言うのに使います
22:20
%@os_log ではデフォでprivate
Avatar
omochimetaru 10-Jun-20 10:20 PM
ほお〜、なるほど。
Avatar
niw 10-Jun-20 10:20 PM
ほら、Appleはプライバーシーコンサーンな会社だから。 (edited)
Avatar
omochimetaru 10-Jun-20 10:21 PM
それでログの書式パラメータを転送して維持しておきたいのか
Avatar
niw 10-Jun-20 10:22 PM
そうですねえ
Avatar
omochimetaru 10-Jun-20 10:22 PM
”\(private: foo)” なら自作できそう
22:23
書式って型チェック的に、言語に対して外回りでやることになるから
22:24
Swift的に良い方向は、↑みたいに、カスタム文字列埋め込みを使っていく事じゃなかろうかと思ってる (edited)
Avatar
niw 10-Jun-20 10:24 PM
なるほど
Avatar
omochimetaru 10-Jun-20 10:24 PM
Foundation.NSStriing.init(format:)も
22:25
割と使ってるけど、ヤダな〜と思ってる。
22:26
浮動小数に対する桁数指定子とかが型チェックされない、書式文字列に埋めこまれてるから。
22:26
あーでも多言語化のためには語順入れ替えとかも必要だから文字列埋め込みだけじゃダメかもしれん・・・
22:27
あ、実際には、リテラル文字列に対して型チェックされるんですけど、そのために特別な仕組みでやってるのが気持ち悪いという事です
Avatar
niw 10-Jun-20 10:30 PM
ほかの言語はどうなんでしょうね
Avatar
omochimetaru 10-Jun-20 10:30 PM
言語というか、swiftコンパイラだと
22:31
言語はc++だけど、そこは凝った仕組みがあって
22:31
書式文字列を定義するDSLがあって、それがc++に事前コンパイルされて
22:32
C++側から見ると、書式文字列ごとに、引数の型がオーバーロードされた関数として生成されます (edited)
22:33
だからc++言語の上で、パラメータの型がちゃんと関数の引数の型としてチェックされるし、 複数形のsをつけるとかのちょっとした条件式も使えるし
22:33
あれは理想的だなと思う
Avatar
niw 10-Jun-20 10:48 PM
ただとても特別な仕組みだと。
Avatar
omochimetaru 10-Jun-20 10:49 PM
そうですね、c++言語とは別に専用言語を事前コンパイルするので・・・
Avatar
koher 17-Jun-20 10:19 AM
前に、参照を維持し続けるだけのための方法について話しませんでしたっけ?検索してもうまく見つけられなかったんですが・・・。たとえば、
do { let _ = publisher.sink { value in ... } ... }
ってやっちゃうと即時キャンセルされちゃうけど、 let cancellable = にしても、その後使わないから警告になっちゃうから、ただスコープの間参照を保持しつづけてくれるみたいなの。
(edited)
10:20
標準ライブラリにそんなやつがありませんでしたっけ?
Avatar
tarunon 17-Jun-20 10:21 AM
deinit dealloc辺りでここで検索すると出てきそう
10:23
@tarunon ありがとうございます!
😉 1
Avatar
niw 19-Jun-20 03:34 AM
public extension で名前被りがあったときってどうやって解決されるんですかね
03:34
public extension UIView { public func neko() -> String { "meow"} } が複数存在したときとか
Avatar
Kishikawa Katsumi 19-Jun-20 03:58 AM
どっちも使用できる状況だったらAmbiguousになるんじゃなかったでしたっけ
03:59
importをするかしないかで区別できる場合は呼び分けられるとかそんなんじゃなかったかな。。
03:59
呼び分けられるというか、コンパイル単位でAmbiguousにならずにどちらか1つを使える。
Avatar
niw 19-Jun-20 04:02 AM
importするかしないかで変わる感じか...
04:02
module名付加で区別みたいなこともできないのか...
Avatar
omochimetaru 19-Jun-20 04:09 AM
メソッドに関してはmodule名による完全修飾はできないですね。
04:09
そのモジュールの中でトップレベル関数版を用意しておくしかないと思います。 (edited)
04:09
トップレベル関数ならモジュール名で修飾できるから。
Avatar
niw 19-Jun-20 04:15 AM
なるほど、、、
04:15
厳しい
Avatar
koher 19-Jun-20 05:15 AM
たとえば、 extensionsomeMethod が被ったとして、別ファイルで、
import Foo extension Int { func foo_someMethod() -> Int { someMethod() } }
を作るなどして呼び分ける?
Avatar
omochimetaru 19-Jun-20 05:55 AM
呼び分け用の別名を用意する手もありますね。それだとメソッド名を修飾するのと使う側の手間はあまり変わらないな。 (edited)
Avatar
koher 19-Jun-20 05:59 AM
既存の複数のライブラリを使っていて名前が衝突してしまった場合に、どうしても一つのファイルの中で呼びわけないといけなかった場合の手段という意味で。
Avatar
niw 19-Jun-20 06:26 AM
おー、確かにそれで回避できる
06:26
ていうかそれを実装しなきゃいけないのがしんどい
Avatar
koher 19-Jun-20 06:26 AM
そうですね。しんどいのでうまい方法があればいいんですが( import as とか)。まあ、最悪やらないといけなかったときになんとかする手段ということで。
Avatar
niw 19-Jun-20 06:27 AM
なんらか完全修飾できればよいですねえ
Avatar
koher 19-Jun-20 06:27 AM
foo.(ModuleName)bar とかできるといいですよね。 (edited)
Avatar
niw 19-Jun-20 06:28 AM
module越えがあえてしにくくしてある、っていうのならまあそういう思想も理解できなくはない
06:28
でもそれならいっそextesnionはモジュールを超えられないとかでよかったかもしれない
06:29
foo.[Module]bar() (edited)
Avatar
koher 19-Jun-20 06:29 AM
そうすると protocol に適合して外部モジュールに食わせるとかもできなくなりそうです・・・。
06:29
後ろに []subscript と衝突するかなと。
06:29
[] はいいかもですね。 foo.[Module]bar
Avatar
niw 19-Jun-20 06:29 AM
こうか
06:29
たしかに
Avatar
Kishikawa Katsumi 19-Jun-20 06:30 AM
お、これは受け入れられるんじゃないですか
Avatar
rintaro 19-Jun-20 06:32 AM
Swift's name lookup is…messy. Very messy. This causes a number of problems, and today I'd like to talk about a potential solution for one of them. Swift allows names to be shadowed by declarations in a nested scope. The idea is that, if you import WidgetKit to access its Widg...
Avatar
niw 19-Jun-20 06:33 AM
いろいろなパターンが。
Avatar
koher 19-Jun-20 06:49 AM
foo.Module::bar よりも foo.[Module]bar の方が読みやすそう。 (edited)
Avatar
koher 23-Jun-20 02:54 AM
dropLast(while:)suffix(while:) がほしくなった。 - 履歴のようなものをソート済 Array で持っていて、指定された範囲にマッチするものを抜き出したい。 - 履歴は後ろに積み上がるので、要素追加を O(1) で行うためには昇順で要素を保持する必要がある。 - 指定される範囲は最近のものであることが多いので末尾から検索したい。 この要件を満たすコードを考えると、
history .dropLast(while: { $0.date >= range.upperBound }) .suffix(while: { $0.date >= range.lowerBound })
のようなことがしたくなる。 RandomAccessCollection なら dropLast(while:)suffix(while:) があってもいいと思う。 SortedDictionary があれば解決する話ではあるけど。
Avatar
koher 23-Jun-20 03:23 AM
Avatar
hironytic 23-Jun-20 03:39 AM
suffix(while:) の方は lastIndex(where:) で意図どおりなんでしょうか?
Avatar
koher 23-Jun-20 03:43 AM
lastIndex(where:) だとインデックスしかとれないんで、それを使って SubSequence がほしいですね。
Avatar
hironytic 23-Jun-20 03:43 AM
あ、いや、なんか対照的に firstIndex(where:) なのかと思ったのですが
03:45
ああ、わかりました。残す方なのか。こっちは。
Avatar
koher 23-Jun-20 03:45 AM
drop(while:)prefix(while:) の対になるものがほしい感じです。
👌 1
03:46
prefix(_:Int)suffix(_:Int)prefix(while:)drop(while:)firstIndex(where:)lastIndex(where:) はあるんですよね。
Avatar
hironytic 23-Jun-20 03:49 AM
index(where:)firstIndex(where:) になったように、 drop(while:)dropFirst(while:) に変えたくなってしまいそうなやつですね。
Avatar
koher 23-Jun-20 03:51 AM
そうですねー。 dropLast がないからそのままですが、 dropLast が導入されたら禍根を残しそうですね。
Avatar
lovee 23-Jun-20 09:25 AM
dropLast(while:) がないのは多分複雑どがO(n)になるからじゃないですかね 🤔
09:26
あでも drop も理屈上O(n)になるのか 🤔
Avatar
omochimetaru 23-Jun-20 09:27 AM
無限長でも動くかどうかかな?
Avatar
lovee 23-Jun-20 09:29 AM
あー確かに drop(while:) はSequenceのメソッドだから、dropLast(while:) 作りたいならせめてCollectionじゃないと無理ですね
Avatar
koher 23-Jun-20 09:31 AM
RandomAccessCollection を想定しています。
09:32
末尾から読めればいいから、 BidirectionalCollection でいいのかな? (edited)
Avatar
omochimetaru 23-Jun-20 09:32 AM
後ろから逐次見ていけば良いからRandomAccessはいらなそう
09:32
無印Collectionは逆方向はダメなんですっけ。
09:33
お〜、そうっぽい、無印Collectionはindex(after:)しかないのかあ。
Avatar
koher 23-Jun-20 09:34 AM
index(before:)BidirectionalCollection にしかなくて、なので lastIndex(where:)Collection にはないね。 https://developer.apple.com/documentation/swift/bidirectionalcollection
09:38
GitHub のコードも BidirectionalCollection に更新したけど、問題なくテスト通った。
Avatar
t.ae 06-Jul-20 01:20 AM
01:20
01:20
final classはイニシャライザが自動生成されてる?
01:21
下はFixを押した結果
Avatar
niw 06-Jul-20 01:21 AM
publicが2個ついてる
01:22
めっちゃpublic
Avatar
t.ae 06-Jul-20 01:22 AM
public initにしようとして、でもinitがないのでそこに入ったんじゃないかと
Avatar
hironytic 06-Jul-20 04:42 AM
イニシャライザを1つも作らなかったらデフォルトイニシャライザが自動生成されるんじゃないですかね。finalにかかわらず。
Avatar
t.ae 06-Jul-20 04:48 AM
@swift-5.2.5
class NoValue {} class OneValue { var x: Int } let noValue = NoValue() let oneValue = OneValue(x: 0)
Avatar
swift52 BOT 06-Jul-20 04:48 AM
exit status: 1 with stderr:
<stdin>:2:7: error: class 'OneValue' has no initializers class OneValue { var x: Int } ^ <stdin>:2:22: note: stored property 'x' without initial value prevents synthesized initializers class OneValue { var x: Int } ^ = 0 <stdin>:5:16: error: 'OneValue' cannot be constructed because it has no accessible initializers let oneValue = OneValue(x: 0) ^~~~~~~~
Avatar
hironytic 06-Jul-20 04:48 AM
デフォルトイニシャライザについてはこのあたり。 https://docs.swift.org/swift-book/LanguageGuide/Initialization.html#ID213
Avatar
t.ae 06-Jul-20 04:49 AM
フィールドが全部デフォルト値を持ってる場合は生成されるんですね。
Avatar
hironytic 06-Jul-20 04:49 AM
あ、そうです。
04:51
あと、Access Controlの方をみたら、型のaccess levelが public なら、default initializerは internal になるって書いてありました。そんなこと書いてあったのか。記憶になかった。 https://docs.swift.org/swift-book/LanguageGuide/AccessControl.html#ID20 (edited)
Avatar
t.ae 06-Jul-20 04:52 AM
04:52
finalじゃない場合はrequiredが要求されたり、publicだと同じ現象になったりしますね。
Avatar
hironytic 06-Jul-20 04:55 AM
あーなるほど。プロトコルで init() が要求されてるから、継承したクラスで init() をなくせないように required をつけなきゃいけないということですね。
04:55
finalなら継承する可能性がないから書かなくていいのか。へえ。すごい。
Avatar
tarunon 06-Jul-20 07:34 AM
デフォルトinitializerはstructとかと同じで基本internalというイメージ
Avatar
omochimetaru 15-Jul-20 07:22 AM
import Foundation import XCTest public final class EncodableTests: XCTestCase { struct S: Encodable { func encode(to encoder: Encoder) throws { var c = encoder.singleValueContainer() try c.encode(A()) try c.encode(B()) // EXC_BREAKPOINT } } struct A: Encodable { var a: Int = 1 } struct B: Encodable { var b: Int = 2 } func testEncodeDouble() throws { let encoder = JSONEncoder() _ = try encoder.encode(S()) } }
07:22
2回encodeする裏技が使えなくなってた。
Avatar
nanasi 15-Jul-20 08:14 AM
func encode(to encoder: Encoder) throws { try A().encode(to: encoder) try B().encode(to: encoder) }
08:14
こちらはいけるみたいですね
Avatar
omochimetaru 15-Jul-20 08:15 AM
お〜マジか なるほど
Avatar
omochimetaru 16-Jul-20 09:40 AM
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
💯 1
09:41
1. TextOutputStreamable かつ CustomStringConvertibleの場合 2. TextOutputStreamableの場合 3. CustomStringConvertibleの場合 4. 任意の<T> 5. Any.Type の場合 の5つのオーバーロードがあるっぽい
09:42
4のケースは _print_unlocked っていう謎の関数に転送されていて
09:43
Mirror.swift において定義されている String.init<T>(describing: T) の実装も、 _print_unlocked への転送だった。
09:43
_print_unlocked の実装は結構面白くて
09:46
6-1 最初の分岐が魔法関数 _openExistential を使ってる
if _openExistential(type(of: value as Any), do: _isOptional) { let debugPrintable = value as! CustomDebugStringConvertible debugPrintable.debugDescription.write(to: &target) return }
09:47
_isOptionalは<T> を受けるので必ずopenできるがその先でoptionalかチェックするから、これでAnyの中に入ってるOptionalとかをおそらく必ず展開できて、 OptionalだからCustomDebugStringConvertibleが通る
09:49
その先は 6-2: String分岐, 6-3: TextOutputStreamable分岐, 6-4: CustomSTringConvertible分岐, 6-5: CustomDebugStringConvertible分岐, で、最後のelseが 6-6: Mirror(reflecting: value)
09:50
1が定義されているのは、もし1が無かった場合、2と3のオーバーロード解決が曖昧になるからだと思う。 で、1の実装は2と同じで、 2の実装と3の実装は6-3と6-4と同じになってる
09:51
ということは、2と3は4からの6-Xに対する最適化ショートカットで、1は2と3の都合で必要になった関数
09:51
気になるのは6-5のショートカットが無いことだけど
09:52
もしそれを実装してしまうと(7とする)、 2と3と7の重複組合せを順序付けするためには、 1に相当するやつの(2,7)版、(3,7)版、(2,3,7)版が必要になって
09:52
組合せ爆発するからあきらめたんじゃなかろうか。
09:54
ちなみに、foo はオプショナルの場合の fix-itが2つ出るが、片方は、 String(describing: foo) への書き換えだから、 String.init(describing:) の実装と 4の実装が同じ( _print_unlocked )なのは暗黙的な規約っぽい。
09:56
_print_unlocked は第二引数でStreamを取れるけどstdlib internalなので、 これはユーザーに提供されていない事になる。 String.init(describing:) を使ってエミュレートできるけど、ストリーム処理可能な場合にパフォーマンスロスが出ちゃう。
Avatar
omochimetaru 16-Jul-20 10:05 AM
なんでこれ調べてたかというと
10:06
public func audioPlayerDecodeErrorDidOccur(_ player: AVAudioPlayer, error: Error?) { print("error \(error, "")") }
↑Optionalの時に警告出るけど、第二引数でデフォルト与えるようにしたくて
10:06
(あと.someの時に外側の Optional( ... ) いらん)
10:06
カスタムintepolation書こうとしてた
extension DefaultStringInterpolation { public mutating func appendInterpolation<T>(_ x: Optional<T>, _ defaultValue: String) where T: TextOutputStreamable, T: CustomStringConvertible { if let x = x { self.appendInterpolation(x) } else { self.appendInterpolation(defaultValue) } } public mutating func appendInterpolation<T>(_ x: Optional<T>, _ defaultValue: String) where T: TextOutputStreamable { if let x = x { self.appendInterpolation(x) } else { self.appendInterpolation(defaultValue) } } public mutating func appendInterpolation<T>(_ x: Optional<T>, _ defaultValue: String) where T: CustomStringConvertible { if let x = x { self.appendInterpolation(x) } else { self.appendInterpolation(defaultValue) } } public mutating func appendInterpolation<T>(_ x: Optional<T>, _ defaultValue: String) { if let x = x { self.appendInterpolation(x) } else { self.appendInterpolation(defaultValue) } } }
10:07
多分適切な実装がコレなんだけどなんとかならんかな・・・
Avatar
niw 17-Jul-20 12:12 AM
DidOccur ってめずらしい名前
Avatar
omochimetaru 17-Jul-20 06:45 AM
たしかに。
Avatar
koher 30-Jul-20 02:11 AM
UTF16Viewcount って内部表現が UTF-16 のときは O(1) になりますか?
Avatar
niw 30-Jul-20 02:12 AM
かなあ
02:12
NSStringってわかってるならならcastしてlengthのほうがいいような気がする
Avatar
koher 30-Jul-20 02:14 AM
必要に迫られてるわけじゃないんですけど、 https://qiita.com/kntkymt/items/4f02c6b90462f354de6d を見て気になって。コード見てみたけど多重にラップされててぱっと見ではわからなかった・・・。
普段はiOS/Androidのアプリ開発をしている自分ですが、ここ最近競技プログラミングの人気が爆上がりしている1 という噂は聞いており、やろうかなと思っていた所... AtCoderでSwift5.2が使える様になった との情報を耳...
02:15
まあでも内部表現によって O(1) か O(n) か心配しながら使うより、素直に [Character] とか NSString とかで書いた方が良さそうですね。
Avatar
niw 30-Jul-20 02:16 AM
ちゃんと理解したい気持ちはある (edited)
Avatar
nanasi 31-Jul-20 01:54 AM
@swift-5.2.5
struct Foo { lazy var value = 1 mutating func reset() { $__lazy_storage_$_value = nil } } var foo = Foo() print(foo.value) foo.value = 2 print(foo.value) foo.reset() print(foo.value)
(edited)
swift 1
Avatar
swift52 BOT 31-Jul-20 01:54 AM
1 2 1
Avatar
niw 31-Jul-20 01:55 AM
w
01:55
べんり
Avatar
nanasi 31-Jul-20 01:55 AM
lazyの実体にアクセスする方法あったんですね😮 (edited)
01:56
There is a way to reset lazy var if you want. I think it's probably a bug, but you can access the underlying storage of a lazy var using $__lazystorage$_{property_name} and set it to nil. For example: class A { lazy var foo: Int = { print("A") return 0 ...
Avatar
rintaro 31-Jul-20 06:06 AM
https://github.com/apple/swift/pull/33144 $__lazy_storage_$_{name} への直接アクセスは意図されておらず、塞がれるのでご注意を。
Since #21996, the name of the underlying storage variable of a lazy var has been changed to $__lazystorage$_{property_name}. You couldn&#39;t actually write an identifier in (Swift) source be...
👀 3
Avatar
tarunon 31-Jul-20 06:07 AM
ですよね
Avatar
omochimetaru 31-Jul-20 06:34 AM
あれもしかして、property wrapperのときに $ がキーワードとして使えるようになった影響で穴が空いた?
06:34
元々の $__lazy_... は アクセスしないために $ ついてたのかなって思った。 (edited)
Avatar
niw 01-Aug-20 03:31 AM
べんりなのにな
03:32
easter egg的に残しておく
Avatar
koher 01-Aug-20 03:54 AM
lazy って @Lazy にならないのかな?
Avatar
tarunon 01-Aug-20 04:34 AM
swift3か4のころはlazy foo: Foo!にnilを代入したらreset扱い、というのが動いてましたね
04:36
IUO型が無くなったことでこの挙動もなくなった、だったかな
Avatar
omochimetaru 01-Aug-20 04:38 AM
@Lazyはautoclosureで実装できるんかな?
04:39
コンパイラのコード生成からライブラリに移せると嬉しいですね 既存コードのマイグレーションの問題はあるけど
Avatar
tarunon 01-Aug-20 05:01 AM
@Lazy var foo: Foo = ... これの時に、initialValue/wrappedValueのinitをescaping autoclosureにしていても、宣言した位置で... が評価されてるからダメみたいですね
Avatar
koher 02-Aug-20 12:06 AM
Property Wrapper の Proposal で @Lazy が例に挙げられてなかったっけ?
00:07
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
Avatar
omochimetaru 04-Aug-20 08:59 AM
KeyedDecodingContainer<K> と KeyedDecodingContainerProtocol って
08:59
今更なんだけど
08:59
AnyKeyedDecodingContainer<K> と KeyedDecodingContainer って名前のペアであるべきだったんじゃ?
Avatar
tarunon 04-Aug-20 09:01 AM
takasekさんのツイートかな
09:01
私もそう思います
Avatar
omochimetaru 04-Aug-20 09:01 AM
話してて思った。
Avatar
tarunon 04-Aug-20 09:01 AM
リプ書いてる途中だった
09:01
送ってしまおう
Avatar
omochimetaru 04-Aug-20 09:02 AM
あの時点で AnySequence って存在してたから
09:02
この判断できる可能性あったよね。 (edited)
Avatar
norio_nomura 04-Aug-20 11:33 AM
Codableの実装初期PRでは、 KeyedDecodingContainerKeyedDecodingContainerProtocolに準拠するけど、 KeyedEncodingContainerKeyedEncodingContainerProtocolに準拠してない、 と一貫性がなかったのを思い出した。 https://github.com/apple/swift/pull/9004#pullrequestreview-37206353 (edited)
What&#39;s in this pull request? Now that the core types introduced by SE-0166 have been sunk into the Swift standard library, the stdlib and compiler portions of #8124 and #8125 can be combine...
Avatar
omochimetaru 04-Aug-20 11:34 AM
ほーー
11:34
@omochimetaru @tarunon だいたいのerasureは文脈の汽空域に現れるのでerasureであることを意識させたいけど、DecodingContainerは文脈が閉じてるので、erasureであることすら知識として表現したくなかった…とか?
11:35
ツイッターで話してて、Anyを付けないのはイレイジャとしてのAPIの提供が主たる関心ではないから、という意見を受けて、ありかもと思いました
Avatar
koher 07-Aug-20 10:46 AM
これって仕様?? DictionaryArrayencode される。 @swift-5.2.5
import Foundation struct Foo: Hashable { var value: String } extension Foo: Encodable { func encode(to encoder: Encoder) throws { var container = encoder.singleValueContainer() try container.encode(value) } } let dictionary: [Foo: Int] = [Foo(value: "a"): 42] let data = try! JSONEncoder().encode(dictionary) let string = String(data: data, encoding: .utf8)! print(string)
Avatar
swift52 BOT 07-Aug-20 10:46 AM
["a",42]
Avatar
omochimetaru 07-Aug-20 10:47 AM
KeyがEncodableな場合はそうな気がする
10:47
Stringだったら JS.Object になりませんか?
10:47
なぜならJSのObjectは文字列しかキーに取れないから。
Avatar
koher 07-Aug-20 10:47 AM
うん、 String だと object になる。
Avatar
omochimetaru 07-Aug-20 10:48 AM
もし Foo の Encoding が JS.Array とかだったら
10:48
JS.Object にできないから、保守的に タプルの配列にするしかないと思う
Avatar
koher 07-Aug-20 10:49 AM
single value の string に encode した場合はキーとして使ってほしい気もするけど、そこだけ対処するのは難しいか・・・
10:49
できそうな気もするけど・・・。
Avatar
omochimetaru 07-Aug-20 10:50 AM
実装がだいぶごちゃっとしそうですね
Avatar
koher 07-Aug-20 10:51 AM
JSONEncoder 側は、 encode 前に型で判断してるのか。 (edited)
Avatar
omochimetaru 07-Aug-20 10:51 AM
そうですね
Avatar
koher 07-Aug-20 10:52 AM
そうすると、 encode で対応しようがないよね?
10:52
なんか変じゃない?
Avatar
omochimetaru 07-Aug-20 10:52 AM
対応しようがない?
Avatar
koher 07-Aug-20 10:52 AM
object として encode させる方法がない?
Avatar
omochimetaru 07-Aug-20 10:53 AM
ああ
Avatar
koher 07-Aug-20 10:53 AM
たとえそれをラップしてる型の encode を独自実装しても?
10:53
それはさすがにできるか?
Avatar
omochimetaru 07-Aug-20 10:53 AM
コンテナのところで
10:53
var container = encoder.keyedEncodingContainer() すればできますよ
10:53
それかいったん [String: T] に mapする
10:54
さっきのコードみたいにキーの型のencode()の実装だけで制御するのは無理そう。 (edited)
Avatar
koher 07-Aug-20 10:58 AM
イマイチ処理のフローがイメージできてないけど、
mutating func encode<T>(_ value: T, forKey key: KeyedEncodingContainer<K>.Key) throws where T : Encodable
こいつが呼ばれるときに一度 JSONEncoder に処理が戻って、そこから Encodable.encode が呼ばれるか判断されるってことやんね?
10:58
保持してる側の encode 実装で対処可能ってことは。 (edited)
Avatar
tarunon 07-Aug-20 11:00 AM
takasekさんがその辺なんかtwitterでやってた記憶がある
Avatar
koher 07-Aug-20 11:00 AM
保持してる側を自力実装にするのは辛いなぁ・・・。 (edited)
Avatar
koher 07-Aug-20 11:17 AM
Dictionary のラッパーを用意して、それの encode/decode を実装することにした。さすがに保持してる型の encode/decode は色んなプロパティが生えてて辛いので。
Avatar
omochimetaru 19-Aug-20 06:06 AM
struct Entry { var manyCountArray: [Foo] mutating func update() { ... } } var map: [String: Entry] = ... for item in items { guard var entry = map[item.name] else { continue } entry.update(item) map[item.name] = entry }
↑このパターンって素朴な解釈では map[item.name]var entry で 2つ参照があるから entry.update の中で manyCountArray の要素を変更したら配列のコピーが発生しそうだけど、 どうだろう
(edited)
06:07
map[item.name]?.update(item)
こう書けばmodifyなので参照1つなのが表明できるんだけど。
(edited)
Avatar
koher 19-Aug-20 06:13 AM
updatemanyCountArray を変更するならコピー発生するんじゃないかな?( entry に一度代入するパターンのとき) (edited)
06:16
map[item.name]?.update(item)
のパターンで書くとき、根っこから深くなればなるほど、そのパスをたどらないといけなくて辛いなと思うんだけど、変数に代入する代わりに inout なクロージャに渡して別名付けるとかすればいいのかな。
06:16
modify(map[item.name]) { entry in entry.update(item) }
的な。
06:17
参照すべきものが二つになった瞬間に詰みそう。
Avatar
omochimetaru 19-Aug-20 06:26 AM
最適化で map[item.name] の get から set までに map[item.name] が触られていないことを検出して、entry へのコピーを共有に書き換えてくれたらコピーされずに済みそうだけどそこまでやってくれるのかなあと思って。
06:27
変数に代入する代わりに inout なクロージャに渡して別名付けるとかすればいいのかな。
そうですね。僕は protocol Modifiable を作って
map[item.name]?.modify { entry in entry... entry... }
って書いてます実際は
06:28
2つになっても modify の入れ子にしたら書けますよ
06:29
ただこういうCoWも含めたコピーの振る舞いを気にしてコードを書くのは言語としては難しいし微妙だなあと思って。
Avatar
koher 19-Aug-20 07:02 AM
同じツリーに属してる二つの枝葉を modify しようとしたら inout で同時編集のエラーにならない?
Avatar
omochimetaru 19-Aug-20 07:03 AM
同じツリーに属してるときは、共通部分までは一緒のmodifyにしてないとだめですね。
07:04
foo.bar.modify { (bar) in bar.a.modify { (a) in bar.b.modify { (b) in bar.a = a + b bar.b = a - b } } }
↑これはいけるはず
(edited)
07:04
foo.bar.a.modify { (a) in foo.bar.b.modify { (b) in
↑これはだめ
(edited)
Avatar
koher 19-Aug-20 07:05 AM
bar.a.modify { (a) in bar.b.modify { (b) in
bar に対する同時編集にならない?
(edited)
Avatar
omochimetaru 19-Aug-20 07:05 AM
ab が stored property なら 分割される
07:05
computed property だとだめ
Avatar
koher 19-Aug-20 07:06 AM
そういうルールなのか。 subscript は computed だから↓ができないのか。
swap(&array[i], &array[j])
Avatar
omochimetaru 19-Aug-20 07:07 AM
そうそう。
07:07
そうすると分岐するところがArrayかDictionaryだとだめか・・・
Avatar
koher 19-Aug-20 07:08 AM
そうすると、 stored だけどジェネリック関数の型パラで受けたらプロトコルでの宣言が var foo: Foo { get } になっててダメとかある?
07:09
ある型のカプセル化されたプロパティが stored か computed かで挙動が変わるってちょっと微妙な気が・・・。 stored を computed に変えたらコード破壊されるかもしれないってこと?
Avatar
omochimetaru 19-Aug-20 07:10 AM
プロトコルで受けたらcomputedあつかいになってだめはありえる気がする・・・
stored を computed に変えたらコード破壊されるかもしれない
そう
Avatar
koher 19-Aug-20 07:12 AM
そうすると分岐するところがArrayかDictionaryだとだめか・・・
結構ありそう・・・。
users[i].modify { user1 in users[j].modify { user2 in guard user1.points >= points else { return } user1.points += points user2.points = min(user2.points + points, 9999) } }
`
(edited)
Avatar
omochimetaru 19-Aug-20 07:12 AM
@swift-5.3.3
func modify<T>(_ t: inout T, _ f: (inout T) -> Void) { f(&t) } struct S { var a: Int = 3 var b: Int = 1 } var s = S() modify(&s) { (s) in modify(&s.a) { (a) in modify(&s.b) { (b) in a = a + b b = a - b } } } print(s)
Avatar
swift53 BOT 19-Aug-20 07:12 AM
S(a: 4, b: 3)
Avatar
omochimetaru 19-Aug-20 07:13 AM
@swift-5.3.3
func modify<T>(_ t: inout T, _ f: (inout T) -> Void) { f(&t) } struct S { var a: Int = 3 var b: Int { get { _b } set { _b = newValue } } var _b: Int = 1 } var s = S() modify(&s) { (s) in modify(&s.a) { (a) in modify(&s.b) { (b) in a = a + b b = a - b } } } print(s)
Avatar
swift53 BOT 19-Aug-20 07:13 AM
exit status: 1 with stderr:
<stdin>:14:12: error: overlapping accesses to 's.a', but modification requires exclusive access; consider copying to a local variable modify(&s.a) { (a) in ^~~~ <stdin>:15:16: note: conflicting access is here modify(&s.b) { (b) in ^~~~
Avatar
omochimetaru 19-Aug-20 07:13 AM
確認した。
Avatar
koher 19-Aug-20 07:13 AM
これはちょっと微妙な挙動だな・・・。気持ちはわかるけど。
Avatar
omochimetaru 19-Aug-20 07:14 AM
ちなみに
07:14
Arrayに.swapAtメソッドがあるのはそのためです。
07:15
Swift.swap(a[i], a[j]) は違反だけど a.swapAt(i, j) はOK
Avatar
koher 19-Aug-20 07:15 AM
@swift-5.3.3
func modify<T>(_ t: inout T, _ f: (inout T) -> Void) { f(&t) } protocol P { var a: Int { get set } var b: Int { get set } } struct S: P { var a: Int = 3 var b: Int = 1 } var s = S() func foo<T: P>(_ s: inout T) { modify(&s) { (s) in modify(&s.a) { (a) in modify(&s.b) { (b) in a = a + b b = a - b } } } print(s) } foo(&s)
(edited)
Avatar
swift53 BOT 19-Aug-20 07:15 AM
exit status: 1 with stderr:
<stdin>:15:16: error: overlapping accesses to 's', but modification requires exclusive access; consider copying to a local variable modify(&s.a) { (a) in ^~~~ <stdin>:16:20: note: conflicting access is here modify(&s.b) { (b) in ^~~~
(edited)
Avatar
omochimetaru 19-Aug-20 07:15 AM
fooの冒頭で var s = s が必要ですね
Avatar
koher 19-Aug-20 07:16 AM
var にコピーじゃなくて inout にした。 overlapping になった。
07:17
Arrayに.swapAtメソッドがあるのはそのためです。
うん、しかたないんだけど Swift の微妙なところの一つだと思ってる・・・。
Avatar
omochimetaru 19-Aug-20 07:24 AM
高速化のために値型+参照を安全に使える言語として設計した結果、
07:24
カジュアルに値型を使うことになってるけど、 (edited)
07:25
特にその高速性が必要ない状況では、排他則にたまに引っかかるのはデメリットのほうが大きそうですね
07:25
上級者向けの言語設計になってると思う。
Avatar
koher 19-Aug-20 08:44 AM
一つの解決策は、変数に保存する代わりにKeyPathに保存することかなぁ。
08:45
Optional挟んだKeyPathに確か書き込めなかったと思うんだけど、それ辛いよね。
Avatar
omochimetaru 19-Aug-20 08:45 AM
変数に保存する代わりにKeyPathに保存すること
どういうことですか?
08:46
Optional挟んだKeyPath
これも、なんのことか?
Avatar
koher 19-Aug-20 08:48 AM
let a = foo.bar.baz.qux a.x += 1 a.y *= 2
みたいな一時的に変数に保存して操作することができないから modify を使ってたけど、
08:48
オーバーラップの問題があるから、常に根っこからアクセスする前提で、変数に一時保存する代わりに KeyPath を保存して操作する手があるかなと。
Avatar
omochimetaru 19-Aug-20 08:49 AM
ああなるほど
08:49
ツリーをめぐるのを root[keyPath: keyPath] で書けば毎回短く書けるからか。
Avatar
koher 19-Aug-20 08:49 AM
うん。
Avatar
omochimetaru 19-Aug-20 08:50 AM
それでコピーしないように書けると・・・。
Avatar
koher 19-Aug-20 08:50 AM
でも、 ?. が挟まると writable にできない…。
Avatar
omochimetaru 19-Aug-20 08:50 AM
ほ〜 しらんかった
Avatar
koher 19-Aug-20 08:51 AM
たしか Forum でも不満が出てたけど、そういう設計なんだって押し切られてた気が。
Avatar
koher 24-Aug-20 04:31 AM
async なメソッドでもメソッドコール中は self が retain されてて await してる間に self が解放されることはないのかな? (edited)
Avatar
omochimetaru 24-Aug-20 04:32 AM
そこのポリシーがasyncだから変わるってことはないように思います。
Avatar
koher 24-Aug-20 04:33 AM
強制 strong self だけど、 async/await は必ず終わる前提だから問題になることはないのか。前も似た話した気がしてきた。
Avatar
omochimetaru 24-Aug-20 04:34 AM
それもそう思います。リークにはならない。
Avatar
koher 24-Aug-20 04:34 AM
あと、これも前に話した気がするけど、 mutating func の中で await したらその後は変更不能になるよね?すごく使いづらそうな気が・・・。 (edited)
Avatar
omochimetaru 24-Aug-20 04:34 AM
相互再帰して一生終わらない呼び出しを作ることとかはできるだろうけど
04:34
まあそれはそれで一生終わらない呼び出しの間一生解放されないのは正しいし。
04:35
その後は変更不能に
何がですか?
Avatar
koher 24-Aug-20 04:36 AM
self が。
Avatar
omochimetaru 24-Aug-20 04:36 AM
mutating funcasync mutating func の間違い?
Avatar
koher 24-Aug-20 04:36 AM
mutating func foo() async -> Bar
Avatar
omochimetaru 24-Aug-20 04:36 AM
asyncは後ろか。
04:37
その後が変更不能になるというのがよくわからない、なぜそうなるの?
Avatar
koher 24-Aug-20 04:38 AM
await の後ろって非同期コールバックと同じだと思うんだけど、非同期コールバックから self を変更できないのと同じことにならない?
Avatar
omochimetaru 24-Aug-20 04:39 AM
ならないと思う
04:39
非同期コールバックがselfを変更できないのは、再代入先がないというか、
04:39
そのメソッド呼び出し自体は脱出して終わっているからで
04:39
asyncの場合は、
04:39
asyncなfunc自体が終わるのはそのawaitが終わったあとだから
04:40
コルーチンコンテキスト上の値としてselfへのinout参照がずっと残っているはず
Avatar
koher 24-Aug-20 04:40 AM
呼び出し側が async であることが強制されることで、書き込み先が消えないのか。
Avatar
omochimetaru 24-Aug-20 04:41 AM
はい。
04:41
普通のfuncがゆっくり実行されてるようなイメージ。
04:41
終わらないまま戻ってこれるのがコルーチン。
Avatar
koher 24-Aug-20 04:42 AM
そうすると、 async/await だと今の値型と非同期処理の相性の悪さを解消できるのか。
Avatar
omochimetaru 24-Aug-20 04:43 AM
おー、そういうことになりますね
Avatar
koher 24-Aug-20 04:43 AM
それは単に書きやすくなる以上の恩恵になりそう。
Avatar
omochimetaru 24-Aug-20 04:43 AM
そのinout参照絡みで変な事が起こらないことも、排他則が同じように効いてきて保護されるはず
Avatar
koher 24-Aug-20 04:46 AM
なんかあんま解決してない気がしてきた。
04:47
非同期処理投げてさっさとメソッド抜けたいときには beginAsync を使うわけで、 beginAsync を挟むと結局 self 変更できなくなる。
Avatar
omochimetaru 24-Aug-20 04:48 AM
たしかにasyncとnon-asyncの境界は結局面倒なことになりますね。
Avatar
koher 24-Aug-20 04:51 AM
Button("Run") { self.foo = heavyOperation() }
↑の heavyOperation が重いから非同期にしたところで、
Button("Run") { beginAsync { self.foo = await heavyOperation() } }
みたいになって self を更新できない。ただし、 SwiftUI の @State なら更新できるのがややこしいけど。
Avatar
tarunon 24-Aug-20 09:30 AM
これって結局元々の非同期+クロージャコールバックの書き方と等しいわけで、クロージャコールバックとして考えると@Stateでしか更新できないというのは、正常なように思える (edited)
Avatar
koher 24-Aug-20 09:47 AM
はい、 @State でしか更新できないのは正当なんですけど、↑のようなコードは self を書き換えられなくなるけど、 foo が値型でも @State なら書き換えられる(ので例としてちょっとややこしいけど)という意でした。 (edited)
Avatar
tarunon 24-Aug-20 10:20 AM
@Stateは値型の皮を冠った参照なので…
Avatar
koher 24-Aug-20 10:22 AM
ですねー。そこが便利さを生んでるですけどそこがややこしいんですよね・・・。
Avatar
koher 01-Sep-20 07:33 AM
@swift-5.2.5
func main() { let a: Result<Int, Never> = .success(42) print(a.get()) } main()
Avatar
swift52 BOT 01-Sep-20 07:33 AM
exit status: 1 with stderr:
<stdin>:3:11: error: call can throw, but it is not marked with 'try' and the error is not handled print(a.get()) ^
Avatar
koher 01-Sep-20 07:33 AM
@swift-5.2.5
extension Result where Failure == Never { func get() -> Success { switch self { case .success(let value): return value } } } func main() { let a: Result<Int, Never> = .success(42) print(a.get()) } main()
Avatar
swift52 BOT 01-Sep-20 07:33 AM
42
Avatar
koher 01-Sep-20 07:33 AM
↑この extension 標準でほしくないですか?
07:34
Typed Throws が導入されて、標準の getthrows Failure になれば解決するのかな。
Avatar
omochimetaru 01-Sep-20 08:48 AM
typed throwsで自動解決したらスマートですね たしかプロポーザルの時にもそれは提案されてたけど、Never as bottomがまだだったから飛ばされたんだっけな?
Avatar
tarunon 01-Sep-20 08:49 AM
そもそもの話で言うと、Resultを返す構造自体がFailure==Neverの時にResult<T>ではなくTを返すべき、というのが根底にありそう
Avatar
omochimetaru 01-Sep-20 08:49 AM
たしかに?
Avatar
koher 01-Sep-20 08:49 AM
それって tagged union じゃなくて untagged union な世界観な気も。
Avatar
omochimetaru 01-Sep-20 08:50 AM
ObservableやPromiseと違ってResultは外せるなあ。
Avatar
tarunon 01-Sep-20 08:50 AM
taggedかuntaggedかはあんまり関係ないと思うけど
Avatar
omochimetaru 01-Sep-20 08:50 AM
エラーのないそれはそもそもただのTと等価だ
Avatar
tarunon 01-Sep-20 08:51 AM
もっと言うとOptional同様サブタイピング関係が定義できれば〜というのがありそう
08:51
個人的にはOptionalのサブタイピングは嘘なので、そっちの方向は嫌なんだけど
08:51
やりたいことの本質はそれに見える
Avatar
koher 01-Sep-20 08:51 AM
Foo|Never == Foo が自動的に成り立つという意味で < untagged
Avatar
tarunon 01-Sep-20 08:52 AM
taggedでも、そういうルールを作れば成り立ちそうな気はしていますね
Avatar
koher 01-Sep-20 08:52 AM
そういう意味では Typed Throws は良い塩梅なんじゃないですか? tagged と等価だけど throws Never は消える。
Avatar
omochimetaru 01-Sep-20 08:55 AM
たるのんの言うようにするためには、Result.mapErrorに対して結局where U == Neverのオーバーロードが必要になるから
08:55
定義回数を減らすためにはやっぱりResult<T,Never>.get()はあったほうがよさそう
08:56
Resultを作る側で対応しようとするとそのたびにオーバーロードが必要
08:57
typed throwsだとResultに限らず全部タダでついてくるのでベスト
08:57
そもそもtyped throwsうまくいくのかイマイチ想像つかんけど・・・
Avatar
tarunon 01-Sep-20 08:57 AM
個人的にはtyped throwはあんまり筋良くなさそうという言語化できてない懸念(直観に近い)があるんですが (edited)
08:58
まあ大体Javaのせいなんだが
Avatar
koher 01-Sep-20 08:58 AM
アプリ開発において typed にこだわると邪魔になると思います。
Avatar
omochimetaru 01-Sep-20 08:58 AM
エラー型の再定義をするか雑にSwift.Errorにアップキャストしちゃうのかで毎回悩みそう
Avatar
koher 01-Sep-20 08:58 AM
ライブラリにはほしい気もしますが、エラーの型設計が難しい。 (edited)
Avatar
tarunon 01-Sep-20 08:58 AM
Resultとの棲み分けで良い塩梅なんじゃないか、というのはある
Avatar
koher 01-Sep-20 08:59 AM
Typed Throws ないから Result 使ってるってのは本末転倒だと思うんですよね。
08:59
async/await 入ったら Result 使いたいケースも減るし。
09:00
デフォルトは Untyped Throws だけど、 Typed Throws という選択肢があってもいいとは思うんですよね。
09:01
Forum で話されてるように、 throws に複数の型を書けるのは止めた方が良いと思います。
Avatar
tarunon 01-Sep-20 09:01 AM
Resultのためにany Error: Errorになったのを考えると
Avatar
omochimetaru 01-Sep-20 09:02 AM
Typed Throws ないから Result 使ってるってのは本末転倒
そう思う。Swift 1.xに戻ってしまう。Swiftのtry-throws構文はJavaとは違ってよくできてる。
(edited)
Avatar
tarunon 01-Sep-20 09:02 AM
やはりというかtyped Errorはマイノリティみを感じる要因でもある
Avatar
koher 01-Sep-20 09:02 AM
Typed にこだわってる範囲ではきちんと API ごとに型付けされたエラー型に包み直す。 < throws に書けるのは一つの型のみ
Avatar
omochimetaru 01-Sep-20 09:02 AM
Resultってなんでエラーの型パラメータもってるんだっけ・・・
Avatar
tarunon 01-Sep-20 09:02 AM
複数Errorを書こうとするなら、まずその前にuntagged unionがいる
Avatar
omochimetaru 01-Sep-20 09:03 AM
いや、合成用のenumを定義すれば、そのままでも大丈夫だよ
Avatar
tarunon 01-Sep-20 09:03 AM
それはそうだが、提案のそれはユーザーサイドでenum書きたくねーぜという話でしょ (edited)
Avatar
koher 01-Sep-20 09:03 AM
Java 、あそこだけ untagged union になってて、 catch でも union っぽい記法になってるのおもしろい。もうどうせなら untagged union 導入しちゃえばいいのに。
Avatar
omochimetaru 01-Sep-20 09:04 AM
そういうユーザーは Swift.Error にアップすればいいんじゃないかしら。
Avatar
tarunon 01-Sep-20 09:04 AM
だったらtyped throwsいらねーじゃん、で議論がループする
09:04
typed throwsに突入する前に、多分色々前提があって
Avatar
omochimetaru 01-Sep-20 09:04 AM
いやそれだとResultのエラー型パラメータもいらないという事になるw
Avatar
tarunon 01-Sep-20 09:04 AM
それを埋めていかなければいけないの気がするね
Avatar
koher 01-Sep-20 09:05 AM
any Error: Error については、 throws Errorthrows と等価であることを扱うためにも意味あるんじゃないでしょうか。
Avatar
omochimetaru 01-Sep-20 09:05 AM
自分でやってて、ロジックエラーとしてこれだけはありえる、みたいな
09:05
下層のエラーが浮かんでくるケースとは別で
Avatar
koher 01-Sep-20 09:05 AM
僕はアプリ開発においてほとんどのケースで Untyped なエラーで十分だと思っていて、本当に必要なところやライブラリなんかで選択的に Typed が使えるというのが良いと思います。
Avatar
omochimetaru 01-Sep-20 09:06 AM
明確に処理結果の成功以外のバリエーションでエラーが列挙できる状況はあって
09:06
そういうときはenumにしてるけど、typed throwsがあったらバッチリはまるんだけどなあと思うことはあるよ
Avatar
tarunon 01-Sep-20 09:06 AM
ResultにErrorの型パラを入れないという選択肢もあったけど、any Error:Errorの択が取られたのだよな、という
Avatar
koher 01-Sep-20 09:08 AM
それと同じように Typed Throws を入れるという選択をするときに any Error: Error が実現されてなければ同じ話になったんじゃないでしょうか? Typed Throws は不要というより単に話が進んでないだけで。
09:09
今思えば、 Result 入れないって言ってたのに急に入れる方向に傾いた背景に、 SwiftUI と Combine があった可能性があるかもしれない。 (edited)
Avatar
tarunon 01-Sep-20 09:10 AM
それはありそうだなぁ、特にCombine
Avatar
koher 01-Sep-20 09:10 AM
だから先に Result を進めないといけなかったとか。一方で Typed Throws に急ぎの事情はない(し Result と違って実装も大変だ)から話が進んでない。
09:10
2016 年には、 Joe Groff が Result は入れないという結論になったって言ってましたからね。
Avatar
omochimetaru 01-Sep-20 09:11 AM
asyncとかのほうがさっさと欲しいですしね。
Avatar
koher 01-Sep-20 09:11 AM
で、裏で SwiftUI 作ってる中で、こういうケースでないと困るよというユースケースが溜まってきて、考えを改めたのかなと。
Avatar
tarunon 01-Sep-20 09:17 AM
asyncとthrowsで解決できるのはFutureまでですからね。一般的なPublisherに拡張しようとするとyield/generatorが必要になってくる
09:18
それら全部をちゃんと提供するとなると重すぎなので一旦Resultになる、と言うのは理解できます
Avatar
koher 01-Sep-20 09:18 AM
ですねー。
09:19
Result だとサクッと入れられるし、 async/await や Typed Throws ですら Result と比べると相当重いアップデートですし。
09:25
ResultFailure == Never のときに keypath member lookup あると便利そうじゃないですか?
09:25
@swift-5.2.5
@dynamicMemberLookup enum MyResult<Success, Failure: Error> { case success(Success) case failure(Failure) subscript<T>(dynamicMember keyPath: KeyPath<Success, T>) -> T where Failure == Never { switch self { case .success(let value): return value[keyPath: keyPath] } } } struct User { var name: String var age: Int } let user: MyResult<User, Never> = .success(User(name: "Name", age: 42)) print(user.name)
Avatar
swift52 BOT 01-Sep-20 09:25 AM
Name
Avatar
koher 01-Sep-20 09:26 AM
さらに逃げの方向ですが。
Avatar
tarunon 01-Sep-20 01:10 PM
これを公式に出すならResult<T, Never>をTに暗黙変換出来るようにしてしまったほうが筋が良いように思える
Avatar
koher 01-Sep-20 03:06 PM
変な暗黙変換が加わるのは嫌ですねぇ・・・。 Result はエラーハンドリングにおいてサブ的な位置づけだし。 keypath memberlookup はやりすぎとしても、最初に書いた try なしの get は標準でできて良いと思います。 (edited)
Avatar
tarunon 02-Sep-20 07:44 AM
ちゃんと言語化出来ていなかったと思うので、もう一度説明すると - Result<T, Never>とTを暗黙変換するのは流石にきついものがある - しかしResultを無理くり拡張するのは暗黙変換より筋が良いかと言うと… - 故に、Resultを返す側のIFとして、Failure==Neverのときは直接Tを返すインターフェイスのオーバーロードであったほうが末端の利用者にとっては嬉しい場面が多そうだ。 - のでnot throwsのget()が存在しないんじゃないか という推論です。でもCombineのextensionとか見てると、not throwsのget()はproposal書けば案外すんなり通るんじゃないかなとも思えてきました。 (edited)
07:48
例えばこんな感じで、Resultを返す方にdisfavoredOverloadをつけておけば、NeverのときにResultでないTを優先出来たりするので。
struct MyClass<T, Failure: Error> { @_disfavoredOverload func getResponse() -> Result<T, Failure> { fatalError() } } extension MyClass where Failure == Never { func getResponse() -> T { fatalError() } } let t = MyClass<Int, Never>().getResponse()
07:48
Resultが欲しい場面はクロージャの引数とかなんですが、同じ使い方で成り立つ (edited)
Avatar
koher 10-Sep-20 09:25 AM
ふと思ったけど、
func on(_ queue: DispatchQueue) async { await suspendAsync { continuation in queue.async { continuation(()) } } }
みたいな関数を作ったら、
func foo() { let x = await bar() await on(.main) self.label.text = x }
みたいなことできそう。
Avatar
yutailang0119 10-Sep-20 09:28 AM
Kotlin Coroutinesっぽいみため (edited)
Avatar
koher 10-Sep-20 09:29 AM
よく考えたら、普通に DistatchQueue.asyncasync になりそう。
func foo() { let x = await bar() await DispatchQueue.main.async() self.label.text = x }
09:29
でも await on(.main) の方が下記心地良さそう。
09:29
@yutailang0119 Kotlin Coroutines と実質同じでしょうね。
😋 1
09:30
Kotlin は await 相当のマークが要らないみたいだけど。
Avatar
koher 14-Sep-20 05:53 AM
Combine のこのメソッド、禁断の技使ってないですか?前に flatten で回避されたやつ。 https://developer.apple.com/documentation/combine/future/replacenil(with:)
05:54
func replaceNil<T>(with output: T) -> Publishers.Map<Future<Output, Failure>, T> where Self.Output == T?
05:55
where Self.Output == T? の部分。 Parameterized extensions https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md#parameterized-extensions 代わりの。 (edited)
Avatar
tarunon 14-Sep-20 06:15 AM
昔は壊れたけど今は壊れなくなってる…?
Avatar
koher 14-Sep-20 06:20 AM
昔(によるけど)もできたけど、 ABI stability が達成できないからとかで Proposal 上げた人が取り下げた件があったと思います。
Avatar
omochimetaru 14-Sep-20 12:38 PM
自分もずっと flatten 使ってるけど禁断なんだろうか
Avatar
tarunon 14-Sep-20 12:39 PM
昔はArray<Array>以外から呼べて酷いコンパイルエラーが出てた記憶があります
Avatar
omochimetaru 14-Sep-20 12:41 PM
ふむ
12:41
呼べて、コンパイルエラー?
12:41
コンパイルエラーなら呼べない。
Avatar
tarunon 14-Sep-20 12:42 PM
IDE上で警告が出ないがコンパイルエラーが出る、だったかな
Avatar
omochimetaru 14-Sep-20 12:42 PM
補間候補に出てきちゃうってこと? (edited)
Avatar
tarunon 14-Sep-20 12:44 PM
そうそう
12:44
何かdiscordで話題にしてた気がするんだよな〜
12:44
野村さんいたはず
Avatar
koher 14-Sep-20 02:26 PM
あー、 tarunon さんが補完の話してたのなんとなく覚えてます。
14:28
Forum の方は、これで flatten 実装できるって話になったけど、もし Parameterized Extensions が実現されたら ABI 変わっちゃうから今は追加しない方が良いのでは?みたいな話が出て取り下げられてたはず。
Avatar
tarunon 14-Sep-20 04:42 PM
16:43
なお野村さんは居なかったw
Avatar
omochimetaru 14-Sep-20 09:45 PM
TLDR: I propose @StatementLifter. Hello. I've read this thread in broad strokes. And I've seen some interesting conversations about many new names. There are some good ideas, but I'm writing because I got a better idea from there. The name of function should be represent...
21:46
Function Builderのレビュースレッドで、「Function Builderって名前は微妙じゃない?」という話題がずっと続いていたので、 自分でも考えて、「Statement Lifter」を提案してみました。
Avatar
koher 15-Sep-20 01:32 AM
Declarative Builder とか?
01:34
単に @builder とかでもいい気も・・・。 (edited)
Avatar
omochimetaru 15-Sep-20 09:20 AM
この機能自体はビルダーじゃないと思うんですよね。この機能を使うとビルダーが組めるよというだけで。
Avatar
koher 15-Sep-20 10:01 AM
これによって作られる型は builder なんじゃない? builder だという情報を付与する attribute の名前に builder が入ってても変じゃない気が。
Avatar
omochimetaru 15-Sep-20 11:47 AM
if文とかwhile文の評価結果を関数呼び出しに変換する機能であって、
11:47
それをSwiftUI.ViewBuilderみたいなビルダーの構成につかうかどうかはユーザー次第と思うんですよね
11:49
例えば、Kotlinの
11:49
receiver closureという言語機能を使うと、HTMLBuilderが構成できるけど
11:49
もし、あれにbuilder closureって名前が付いていたら違和感がある。 (edited)
Avatar
tarunon 17-Sep-20 08:19 AM
swift5.3だとまだFunctionBuilderでfor/whileは使えないんですね
Avatar
omochimetaru 17-Sep-20 08:19 AM
あら
Avatar
koher 17-Sep-20 08:36 AM
if letswitch は使えるようになったんでしたっけ?
Avatar
tarunon 17-Sep-20 08:56 AM
ifletとswitch使えますね (edited)
🙂 1
08:45
@resultBuilder になって再Reviewになりそうな気配がする。
Avatar
tarunon 24-Sep-20 08:46 AM
FunctionBuilderよりは良いのかな
Avatar
omochimetaru 24-Sep-20 08:46 AM
そう思う
08:47
構文変換する魔術について触れてない名前だから個人的には微妙だが・・・ (edited)
08:47
まあ後続の人たちは resultBuilder でググって頑張ってって感じかな。
08:47
(ただの builder は紛らわしいという指摘はあった )
Avatar
tarunon 24-Sep-20 08:48 AM
ブロック内を式指向に変換する、が正しい機能なのだよね
Avatar
omochimetaru 24-Sep-20 08:48 AM
そう思う。
08:48
文指向のSwiftにおいて式指向の魔法を解放する
08:48
式指向にするだけじゃなくてそこに任意のフィルタ関数が挟まるからさらに複雑だけども。
Avatar
tarunon 24-Sep-20 08:49 AM
これで「if式無いんですか?」ってマウント取られた時に、「コンテキストを限定して使えますよ。まさかどこでも使えちゃうんですか?w」って返せるようになった
Avatar
omochimetaru 24-Sep-20 08:49 AM
www
08:50
ややこしい設計だと思うけど、そういうふうに言うとそれっぽいな。
Avatar
koher 24-Sep-20 01:05 PM
if 式ってなんでそんなに人気あんのかよくわかんないんですよね。巨大な式は可読性良くないし、小さな式なら三項演算子でいいし。
Avatar
omochimetaru 24-Sep-20 01:06 PM
let a = { if ... { return 1 } else { return 2 } }()
↑これよく書くけどif式なら楽だなあとは思います
13:06
このままなら三項演算子でいいけど、return 1 のところで 2文書きたかったりする。
Avatar
koher 24-Sep-20 01:07 PM
僕はそのパターンは
let a: Int if ... { a = 1 } else { a = 2 }
で書きます。 a がここで初期化されるのが保証されないというのはあるけど、普通に読めば読めると思う。
Avatar
omochimetaru 24-Sep-20 01:08 PM
aが3回出てくるのが冗長で嫌いなんですよね。
13:08
制御フローがチェックされてるから安全なのはわかるんですけど。
Avatar
koher 24-Sep-20 01:08 PM
return も冗長では?
Avatar
omochimetaru 24-Sep-20 01:08 PM
それはそうですね。
13:08
if - else じゃなくて、
13:08
guard とかだと早期脱出の意味があったりして
13:08
returnで書く意味も出てくるけど。
13:09
値がないときにデフォルト値を構築するみたいな場合は、guard + return のほうがニュアンスが強まってわかりやすい事もある。
13:10
あ、でもその形はそもそもif式にならないか?
Avatar
koher 24-Sep-20 01:10 PM
: Int を書かなきゃいけないというのはあるけど、三項演算子で書けないくらい巨大になるなら型が書いてあった方が読みやすいと思うし。
13:11
guard については、 if で書く場合と比べて早期脱出を意味するという意味で比較対象になりうるとは思う。
Avatar
omochimetaru 24-Sep-20 01:11 PM
Kotlinだったらif式と合わせてreturnも書かないですね。
13:11
というかreturnだとif文を飛び越えて出ていっちゃう。
Avatar
koher 24-Sep-20 01:11 PM
最後の式が戻り値になるのも一長一短だと思うしなぁ。
Avatar
omochimetaru 24-Sep-20 01:12 PM
うーんとだから、最初に書いた即時クロージャの書き方は、if式のマネごとで
13:12
やっぱりif式よりはreturnの分で冗長。
13:12
あーあと、
13:12
koherの変数の左辺を3回書く方式は
Avatar
koher 24-Sep-20 01:12 PM
最後の式が戻り値になるのを全面的に受け入れた上で if 式導入するのはわかるけど。 (edited)
Avatar
omochimetaru 24-Sep-20 01:12 PM
コピペしづらいんですよね。
13:13
代入文の形になってると、別の変数の右辺値のところにコピペしても機能するけど、
13:13
3回出てくると全部リネームしないと再利用できない。スニペットの環境に対する結合度が強い。
Avatar
koher 24-Sep-20 01:13 PM
if 式まるごとコピペするようなときは関数にするのが正解な気も・・・。
Avatar
omochimetaru 24-Sep-20 01:14 PM
僕は結構
13:14
設計をするまえに雑に書いて書きながら設計するんで
13:14
そういう操作を結構やります
Avatar
koher 24-Sep-20 01:14 PM
なるほど。
Avatar
omochimetaru 24-Sep-20 01:14 PM
最終的には関数に切り出すこともあるし、その場に残すこともあるけど
13:14
最終形を見えない状態でガチャガチャ取り回しやすいコード片を意識しがち (edited)
13:16
一度完成させた後に再利用したくなったときはコピペじゃなくて関数化ですね。
Avatar
koher 24-Sep-20 01:17 PM
参照型中心の言語でイミュータブルクラス中心だとどうしても式指向にならざるを得なくて、その一貫性の元に最後の式を戻り値にして return 省略を前提に if 式はわかるけど、
Avatar
omochimetaru 24-Sep-20 01:18 PM
ああ、たしかに。
13:18
値型だとvarが出てきて更新文が出てきますね。
Avatar
koher 24-Sep-20 01:18 PM
Swift みたいな値型中心の言語では話が違うから途中をすっとばして if 式というのは違うと思うから、「 Swift って if 式ないの?」っていうのは Swift 理解してないんだろうなという気持ち。
Avatar
omochimetaru 24-Sep-20 01:19 PM
まあそれはそうですね。
13:19
残念ながら現実は煽ってくるほどの知名度も無いと思う・・・ (edited)
😂 1
Avatar
tarunon 24-Sep-20 01:19 PM
そうかな
13:19
結構私はScalaの民に言われる印象があって
Avatar
omochimetaru 24-Sep-20 01:20 PM
ほう
Avatar
tarunon 24-Sep-20 01:20 PM
個人経験に基づくものかもだけど
Avatar
koher 24-Sep-20 01:20 PM
値型がない言語を使ってるとイメージしづらいだろうなとは思います。
13:20
僕が Swift をやる前は絶対そっち側の意見だったと思うので。
Avatar
tarunon 24-Sep-20 01:21 PM
例えば三項演算子で解決出来ないシーンは結構あって
13:21
if letが出てくると三項演算子だと!を使うことになってモニョいし
Avatar
koher 24-Sep-20 01:22 PM
プロパティの初期値とかはそうですね。 (edited)
Avatar
tarunon 24-Sep-20 01:22 PM
Arrayの要素において2から4個目の値が特定条件で切り替わる、みたいなシーンとか
Avatar
omochimetaru 24-Sep-20 01:22 PM
そのケースは Optional.map にできんかな > if let
Avatar
tarunon 24-Sep-20 01:22 PM
欲しいな〜〜〜ってなることは結構ある
13:22
あー確かに
13:22
Optional1個なら確かにmapで良いんだけど
Avatar
koher 24-Sep-20 01:23 PM
if let ... else は無理かも? < map
13:23
?? でいけるか。
Avatar
tarunon 24-Sep-20 01:23 PM
数個になったときにmapflatMapflatMapflatMapってやるのが
13:23
読みやすいかは疑問
Avatar
omochimetaru 24-Sep-20 01:23 PM
まあそうね。
Avatar
tarunon 24-Sep-20 01:23 PM
ifletはOptionalに対するdo構文の側面もあるので
13:23
沢山使うならこっちの方が良いよね〜とか
Avatar
omochimetaru 24-Sep-20 01:23 PM
mapよりはif let のほうが良いね。
Avatar
koher 24-Sep-20 01:25 PM
それが if で解決できないのって、プロパティの初期化とかを想定してますか?
Avatar
tarunon 24-Sep-20 01:25 PM
プロパティの初期化もそうだし
Avatar
koher 24-Sep-20 01:25 PM
let a: Int if ... { a = 1 } else { a = 2 }
13:25
↑の形では書けないとき。
Avatar
tarunon 24-Sep-20 01:26 PM
Arrayの2番目から4番目…みたいなシチュエーションも
13:26
クッソ冗長になる
Avatar
omochimetaru 24-Sep-20 01:26 PM
Arrayの要素において2から4個目の値が特定条件で切り替わる、みたいなシーンとか
これは 三項演算子と [] 使ってflatMapするか
13:26
varつかうか迷う。
Avatar
tarunon 24-Sep-20 01:26 PM
とにかく冗長になるっていうのがまぁヤなんですよね
Avatar
omochimetaru 24-Sep-20 01:26 PM
でもif式でも、
13:27
2個目の要素をなくすってできないんじゃない?
Avatar
tarunon 24-Sep-20 01:27 PM
例えばpropertyの初期値だと、宣言した箇所とinit内のifって分散しちゃうので
13:27
素直にif式でやる場合はOptionalにしてcompactMapになりそう (edited)
13:28
これがreturnBuilderなら、もう少し進んで
Avatar
koher 24-Sep-20 01:28 PM
そういうケースは resultBuilder が利いてきそうですね。
Avatar
tarunon 24-Sep-20 01:29 PM
Arrayの入れ子を宣言してflattenする、という構文に昇華できるので
Avatar
koher 24-Sep-20 01:29 PM
むしろ if 式よりもよさそう。
Avatar
tarunon 24-Sep-20 01:29 PM
かなり使いやすそうだな〜トか考えてます
13:29
シンプルなif式では無いってところが、難しいポイントなんですが嬉しいところでもありますね
Avatar
omochimetaru 24-Sep-20 01:30 PM
たしかに。
Avatar
tarunon 24-Sep-20 01:30 PM
でまあif式がなくって悲鳴を上げていたの
13:31
例えば
struct Foo { var bar = if let x = productionVersion { ... } else { } }
13:31
凄ーくエッジケースではありますが
Avatar
omochimetaru 24-Sep-20 01:32 PM
あープロパティの初期値の右辺値か。
Avatar
tarunon 24-Sep-20 01:32 PM
この辺とかもinitに分散して宣言と散けなくて済むとか
Avatar
omochimetaru 24-Sep-20 01:32 PM
それは3回書けないね。
Avatar
tarunon 24-Sep-20 01:32 PM
色々な可能性があります (edited)
Avatar
omochimetaru 24-Sep-20 01:32 PM
initで書くと2回書いて、検査はされる。
13:32
(Optionalだとnilのままスルーされる事がある)
👉 1
13:33
あれ微妙だよなあ
Avatar
tarunon 24-Sep-20 01:33 PM
まあOptionalはすくえないかもてすが…w
👉 1
Avatar
omochimetaru 24-Sep-20 01:33 PM
Kotlinだと = null が必須なんだけど、
13:33
こっちのほうがいいなあとよく思う。
Avatar
koher 24-Sep-20 01:33 PM
Optionalnil 初期化必須でいいよね。
13:33
= nil って大したタイプ数じゃないし。
👉 1
Avatar
niw 24-Sep-20 10:04 PM
struct Container<Value> { var value: Value init(value: Value) { self.value = value } func withValue(action: (Value) -> ()) { action(value) } } var container = Container<Any>(value: "foo") container.withValue { value in print(value) container.value = "bar" print(value) }
22:05
swiftc -O a.swift && ./aswiftc a.swift && ./a で結果が異なる (edited)
Avatar
rintaro 24-Sep-20 11:01 PM
最適化のバグっぽい。
Avatar
niw 24-Sep-20 11:18 PM
これvalueがclassへのポインタとかだったりするとcrashする模様 (edited)
23:18
structじゃなくてclassでも起こる
23:18
(発見者: 同僚)
Avatar
omochimetaru 25-Sep-20 03:52 AM
あれ、これLoE違反のはず?
Avatar
rintaro 25-Sep-20 03:53 AM
とも思ったんだけど、どうだろう。mutating だったらそうだけど、value をコピーして渡しているから安全なはず?
Avatar
omochimetaru 25-Sep-20 03:56 AM
withValueメソッドの呼び出しの間は Container に対する read access で、 クロージャの中の container.value への書き込みが write access だから、それがコンフリクトと思ったけど
Avatar
rintaro 25-Sep-20 03:57 AM
Avatar
omochimetaru 25-Sep-20 03:58 AM
withValueの実装まで見た場合はactionの呼び出しの間、Containerへのreadは終わってるから許されるやつか
04:01
表示がbarになるって なかなかアグレッシブだな action の引数だけどコピー省略してポインタ共有になってるのか
Avatar
niw 25-Sep-20 07:15 AM
おー、globalでも...
Avatar
koher 30-Sep-20 04:51 AM
initasync にできない想定なのかな?まだ実装されてないだけ? @swift-nightly -Xfrontend -enable-experimental-concurrency
struct Foo { init() async throws { fatalError() } }
(edited)
Avatar
swiftNightly BOT 30-Sep-20 04:51 AM
exit status: 1 with stderr:
<stdin>:2:12: error: initializer cannot be marked 'async' init() async throws { ^~~~~~
(edited)
Avatar
koher 30-Sep-20 04:51 AM
↓こっちはできる。 @swift-nightly -Xfrontend -enable-experimental-concurrency
struct Foo { func foo() async throws { fatalError() } }
(edited)
Avatar
swiftNightly BOT 30-Sep-20 04:51 AM
no output (edited)
Avatar
koher 30-Sep-20 04:52 AM
あれ?できない? コピペしたときに -emit-sil が含まれてただけだった・・・。 (edited)
04:55
init を非同期にできるのは( Promise を使う JS とかではできない)おもしろい特徴だから是非入れてほしいところ。
Avatar
tarunon 30-Sep-20 05:05 AM
最初からできなくても後から拡張するでも全然いいと思うので、追々proposal上げるのが良いのでは
05:05
互換性に問題はないはず
Avatar
koher 30-Sep-20 05:14 AM
まだ正式な Proposal 出てないですし、実装がまだなだけかもなので、 Proposal 出て init 入ってなかったら意見を上げたいですね。 (edited)
Avatar
omochimetaru 30-Sep-20 05:35 AM
ですね
Avatar
kateinoigakukun 06-Oct-20 10:14 AM
swiftdepsをswiftmoduleに埋め込んでクロスモジュールでインクリメンタルビルドするやつ出てた https://github.com/apple/swift/pull/34196 (edited)
Cross-Module incremental dependencies are a new experimental mode of the Swift driver and frontend. Through a tight partnership between the two, we enable the driver to have far greater visibility ...
Avatar
koher 08-Oct-20 01:43 AM
最近色々出ますね。 https://swift.org/blog/swift-algorithms/
Avatar
Kishikawa Katsumi 08-Oct-20 01:44 AM
これが標準で用意されるのはとてもいい
🙂 1
Avatar
koher 18-Oct-20 02:08 PM
探し方が悪いのかもですが、 API Reference の Int https://developer.apple.com/documentation/swift/int からたどって Comparable に適合しているパスを見つけられなかったんですが、 Int ってどの経路で Comparable に適合しているかわかりますか?
Avatar
omochimetaru 19-Oct-20 02:02 AM
Int
02:02
FixedWidth Integer
02:02
BinaryInteger
02:02
Stridable
02:02
Comparable
02:02
で到達できましたよ。
Avatar
kateinoigakukun 19-Oct-20 02:10 AM
matt先生のswift-doc的なやつでグラフィカルに経路がわかると良さそうですね
02:11
たとえばこんな感じで継承関係がビジュアライズされます https://swiftwasm.github.io/JavaScriptKit/JSObject/
Avatar
omochimetaru 19-Oct-20 02:12 AM
スマホだと見えない?
Avatar
kateinoigakukun 19-Oct-20 02:12 AM
ホントですね、スマホだと絵が出ないや
Avatar
omochimetaru 19-Oct-20 02:12 AM
見えないっぽいんや デスクトップモードにしてもスマホサイトだった
Avatar
kateinoigakukun 19-Oct-20 02:13 AM
Avatar
omochimetaru 19-Oct-20 02:13 AM
いいね。
Avatar
koher 19-Oct-20 02:14 AM
Strideable😳
02:14
integer 関連とか Numeric とかばっかり探してた・・・。
Avatar
omochimetaru 19-Oct-20 02:18 AM
strideableって不思議な型だなぁ
02:18
stride関数を通すとSequenceになるんすね。そのままではSequenceではない。
02:21
でもその定義から数直線上?に乗る事とか、差分の型と値の型が同一である事などが定められるのか
Avatar
koher 19-Oct-20 02:23 AM
stride といえば、最近 AtCoder 用にパフォーマンス計測しながらコード書いてるんだけど、
for k in 2 ... number / m { sieve[k * m] = true }
っていうコードを
for k in stride(from: 2, through: number / 2, by: 2) { sieve[k] = true }
に書き換えたら乗算を減らせて速くなるかと思ったら激遅になっておどろいたんだけど、 Range<Int>ClosedRange<Int> の場合だけ特殊な最適化が行われてる?
(edited)
02:23
それとも + 2 と比べてインクリメントが速い? (edited)
Avatar
omochimetaru 19-Oct-20 02:25 AM
げきおそであれば、
02:25
stridableによる抽象化のディスパッチコストな気がするな
02:25
SILをみるとわかりそう
02:26
インライン化と特殊化がされきってないんじゃないすかね
Avatar
koher 19-Oct-20 02:26 AM
多分、 Range の場合はイテレータとか消えて
for (int i = 0; i < n; i++)
とか相当になってるんだろうと予測してるんだけど
02:27
stride の場合はイテレータで回してるのかなって。
Avatar
omochimetaru 19-Oct-20 02:27 AM
arcodrerはコンパイラオプションは見えるんですか?
Avatar
koher 19-Oct-20 02:27 AM
見れるんだけどどこだっけな
Avatar
omochimetaru 19-Oct-20 02:27 AM
同じビルドして手元で結果を観察するのが良いと思いますよ
Avatar
koher 19-Oct-20 02:27 AM
-Ounchecked なのは間違いない。
Avatar
omochimetaru 19-Oct-20 02:27 AM
予測だと間違いがあると知見にならないし・・・
Avatar
koher 19-Oct-20 02:28 AM
あ、激遅なのは XCTest の measure した結果です。
02:28
-Ounchecked で。
Avatar
omochimetaru 19-Oct-20 02:28 AM
なるほど
02:29
あとは前者だけベクトル化できたとかかなぁ予想では・・・
Avatar
koher 19-Oct-20 02:30 AM
他には、下手に .lazy 使って無駄な Array の生成を防ごうとしたら遅くなったとか、色々おもしろい。
Avatar
omochimetaru 19-Oct-20 02:30 AM
そういうのぜひ調べてわいわいswiftcで話して・・・ (edited)
Avatar
koher 19-Oct-20 02:31 AM
たしかに SIL とか LLVM まで調べたらわいわいのテーマとしておもしろそうだね。
Avatar
omochimetaru 19-Oct-20 02:32 AM
sil最適化は何ステップも通して少しずつコード変形していくので
02:32
これひとつ完全に調べるだけでかなりの事が出てきそう
Avatar
koher 19-Oct-20 02:33 AM
今度 Swift Zoomin' で競プロやるけど、わいわいの方が競プロと相性良さそうな気がする。
02:34
最適化を考慮しまくって、過去問のある問題の最速を目指すとかおもしろそう。
Avatar
omochimetaru 19-Oct-20 02:34 AM
競技プロの会があるならそっちにも需要ありそうですね。 (edited)
02:35
アルゴリズムが思いつくかどうかだけじゃなくて最速コードにする部分の競技性もあるんか。
Avatar
koher 19-Oct-20 02:37 AM
過去問でも提出して時間計測できるからおもしろい。 https://atcoder.jp/contests/abc138/submissions?f.Task=&f.LanguageName=&f.Status=&f.User=koher
AtCoder is a programming contest site for anyone from beginners to experts. We hold weekly programming contests online.
Avatar
omochimetaru 19-Oct-20 02:37 AM
へえー
Avatar
koher 19-Oct-20 02:37 AM
わいわいのみんなで誰が最速を叩き出せるかやってみたらおもしろそう。
02:38
全ユーザーの最速も見れるから、 C++ の最速にどこまで迫れるかとか。
Avatar
koher 19-Oct-20 10:35 AM
@swift-5.3.3 @swift-5.2.5 @swift-5.1.5
func primes(upTo number: Int) -> [Int] { precondition(number >= 0) if number < 2 { return [] } var sieve: [Bool] = .init(repeating: false, count: number + 1) for m in stride(from: 3, through: Int(Double(number).squareRoot() + 1.5), by: 2) { if sieve[m] { continue } let maxK = number / m if maxK < 2 { continue } for k in 2 ... maxK { sieve[k * m] = true } } var result: [Int] = [2] for m in stride(from: 3, through: number, by: 2) { if sieve[m] { continue } result.append(m) } return result } print(primes(upTo: 100))
Avatar
swift52 BOT 19-Oct-20 10:35 AM
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
Avatar
swift51 BOT 19-Oct-20 10:35 AM
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
Avatar
swift53 BOT 19-Oct-20 10:35 AM
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
Avatar
koher 19-Oct-20 10:36 AM
↑のコードを AtCoder の実行環境 https://atcoder.jp/contests/practice/custom_test で実行すると、 import Foundation がないとコンパイルエラーになるんだけど、どういう状態だろう? Swift 5.2.1 だけど、 5.2.1 特有のバグ?そんなバグありましたか?それとも実行環境が特殊?
10:38
↓ 5.2.1 でも実行できたから AtCoder の環境が何かおかしそう? https://swiftfiddle.com/wg6dv2tpofhjdlw3q6zyv46thi (edited)
10:42
↓で実行されてる模様
swiftc -Ounchecked -o {dirname}/a.out {dirname}/{basename} {dirname}/a.out
https://atcoder.jp/contests/language-test-202001
Avatar
kateinoigakukun 19-Oct-20 10:43 AM
リンクに失敗してるみたいですね
10:44
libcがリンクされてないっぽい?
10:46
おー再現しました
Avatar
koher 19-Oct-20 10:49 AM
squareRoot って標準ライブラリですけど libc 依存なんですっけ?
Avatar
Kishikawa Katsumi 19-Oct-20 10:52 AM
AtCoderの環境がSwift.orgがダウンロード提供してるものとは違うっぽいすね。
Avatar
omochimetaru 19-Oct-20 10:52 AM
Swift stdlibは特に断りなくlibcには依存してると思います
Avatar
kateinoigakukun 19-Oct-20 10:52 AM
実装を追っていったところLLVM intrinsic instructionのllvm.sqrt経由でlibmに依存してるみたいです
Avatar
omochimetaru 19-Oct-20 10:53 AM
intrinsic経由なんだ。
Avatar
kateinoigakukun 19-Oct-20 10:56 AM
swiftCoreに対してはautolinkの仕組みが効かないからこういうことになるのか
Avatar
omochimetaru 19-Oct-20 10:57 AM
どういうことなんだ
Avatar
kateinoigakukun 19-Oct-20 10:59 AM
えーと
11:00
Mach-Oにはオブジェクトファイルの仕様としてautolinkの仕組みがあって、オブジェクトファイルに記述されたライブラリをリンカが読んで自動でリンクするんですけど、 (edited)
11:01
ELFはそういうリンカとコンパイラの間のコンベンションが無いので、Swiftは勝手にELFオブジェクトファイルにautolinkセクションを作ってリンカオプションを書いて、
11:03
ドライバがリンカへ渡す入力全体に対して、swift-autolink-extractでautolinkセクションを読んでリンカオプションを集めて、リンカに渡す、っていう仕組みになってるんですけど、
Avatar
omochimetaru 19-Oct-20 11:04 AM
ふむふむ
Avatar
kateinoigakukun 19-Oct-20 11:05 AM
リンカにオブジェクトファイルと一緒に渡されるswiftCoreは特別扱いされていて、リンカオプションがハードコーディングされていて、ドライバ的にリンカの入力の一つとして扱われているわけじゃないので、autolink-extractが走らないんですよね。 https://github.com/apple/swift/blob/main/lib/Driver/UnixToolChains.cpp#L302
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
11:07
なのでswiftCoreが外部のシンボルに依存している、かつそのシンボルがclangリンカドライバが自動で挿入するライブラリに含まれていない場合リンクに失敗すると思います。
11:07
libcはclangリンカドライバが自動で挿入するけどlibmは挿入されない。 (edited)
Avatar
omochimetaru 19-Oct-20 11:07 AM
ドライバ的にリンカの入力の一つとして扱われているわけじゃないので、autolink-extractが走らない
はは〜ん
11:08
めちゃくちゃ細かいバグだね
Avatar
kateinoigakukun 19-Oct-20 11:09 AM
ドライバ博士
Avatar
masakihori 19-Oct-20 11:38 AM
swiftの技巧としては追記していく配列にContiguousArrayを使うだけで速くなります (edited)
11:39
for-inの所はwhereつけて2の倍数を除外 遅くなってた (edited)
11:40
for m in (3...number) where !m.isMultiple(of: 2)
(edited)
👀 1
Avatar
koher 19-Oct-20 01:44 PM
なのでswiftCoreが外部のシンボルに依存している
これについては
実装を追っていったところLLVM intrinsic instructionのllvm.sqrt経由でlibmに依存してるみたいです
ということは、 squareRoot については内部で libc の sqrt に依存してて、環境に寄らないですよね?ということは、
かつそのシンボルがclangリンカドライバが自動で挿入するライブラリに含まれていない場合リンクに失敗すると思います。
この「自動で挿入するライブラリに含まれ」るかどうかが環境に依存してて、 AtCoder は含まれない環境ってことでしょうか?
13:45
おそらく、 Docker か何かのコンテナの上で実行されていると思うんですが、利用しているイメージがそのような環境になってる?
Avatar
kateinoigakukun 19-Oct-20 01:46 PM
OSがどのlibcを提供しているかによるんですかねぇ
13:46
少なくとも手元のLinuxマシンでは再現しました (edited)
Avatar
koher 19-Oct-20 01:46 PM
え、再現って何か手を加えたわけじゃなくて普通に起こったんですか?
Avatar
kateinoigakukun 19-Oct-20 01:47 PM
ですです。
Avatar
koher 19-Oct-20 01:48 PM
swiftbot や SwiftFiddle では起こってないから、何が違うのか知りたいですね・・・
13:49
とりあえず AtCoder だと import Glibc 付けとくのが良さそう。
Avatar
kateinoigakukun 19-Oct-20 01:50 PM
とりあえず手元の環境はこれです
FROM ubuntu:20.04 RUN apt -y update # Install development utils RUN DEBIAN_FRONTEND=noninteractive \ apt install -y wget tar vim openssh-server sudo tmux lldb \ git cmake ninja-build \ clang python uuid-dev \ libicu-dev icu-devtools \ libedit-dev libxml2-dev \ libsqlite3-dev swig libtinfo5 \ libpython2-dev libncurses5-dev \ pkg-config libcurl4-openssl-dev \ systemtap-sdt-dev \ tzdata rsync python-six \ libncurses5 \ libz3-dev python3-distutils
🙏 1
Avatar
koher 19-Oct-20 02:28 PM
AtCoder で↓を実行してみたんですが、
import Foundation let processInfo: ProcessInfo = .processInfo print(processInfo.operatingSystemVersionString)
結果は↓でした。
Ubuntu 5.4.0-1025.25~18.04.1-aws 5.4.60
Avatar
koher 19-Oct-20 04:32 PM
お、前に言語実行環境の募集があったんですが、↓のように書かれてました。(この通りに行われているかはわかりません。)
"適宜sudoをつけてください apt install clang libicu-dev libpython-all-dev wget https://swift.org/builds/swift-5.1.3-release/ubuntu1804/swift-5.1.3-RELEASE/swift-5.1.3-RELEASE-ubuntu18.04.tar.gz tar xvfz ./swift-5.1.3-RELEASE-ubuntu18.04.tar.gz mv ./swift-5.1.3-RELEASE-ubuntu18.04/usr {install_dir} export PATH={install_dir}/usr/bin:""${PATH}"" # パスを通す"
https://docs.google.com/spreadsheets/d/1PmsqufkF3wjKN6g1L0STS80yP4a6u-VdGiEv5uOHe0M/
(edited)
16:32
(↑では 5.1.3 になってますが、実際には 5.2.1 です。)
Avatar
Kishikawa Katsumi 20-Oct-20 01:02 AM
普通にSwift.orgの手順通り提供されているのを ダウンロードしてるだけっぽいですねえ。
01:02
なんで違いが出るんだろう
Avatar
norio_nomura 20-Oct-20 01:31 AM
swiftcを使うとリンクエラーになりますね。ボットはswiftを使ってる。
$ pbpaste|docker-swift-run swiftc -Ounchecked - /tmp/--90f083.o:--90f083.o:function $s4main6primes4upToSaySiGSi_tF: error: undefined reference to 'sqrt' clang-10: error: linker command failed with exit code 1 (use -v to see invocation) <unknown>:0: error: link command failed with exit code 1 (use -v to see invocation) $ pbpaste|docker-swift-run swift -Ounchecked - [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
(edited)
Avatar
Kishikawa Katsumi 20-Oct-20 01:31 AM
あ、なるほど!納得しました。
01:32
swiftcで一回コンパイルしないとビルド時間と実行時間分けられないですしね。
Avatar
koher 20-Oct-20 02:01 AM
なるほど。 swiftc だとダメなんですね。
02:01
ボットも swiftc かと思ってました。
Avatar
norio_nomura 20-Oct-20 03:06 AM
demangleとかも呼べる様にswiftなのです。 @swift-5.3.3 demangle $s4main1aSivp
👀 1
Avatar
swift53 BOT 20-Oct-20 03:06 AM
$s4main1aSivp ---> main.a : Swift.Int
Avatar
kateinoigakukun 20-Oct-20 05:24 AM
なるほどswift コマンドでimmediateモードで走らせるとLLVMのJITで実行されるからllvm.sqrtがlibmのシンボルに依存しない形で実行されるのか (edited)
👀 1
Avatar
omochimetaru 24-Oct-20 04:24 PM
‾ (overline, U+203E) and _ (low line, U+005F) have a good upper-lower relationship. The downside however is that ‾ is a bit harder to type.
16:25
型として不明な型を表す_を導入する提案
Avatar
kateinoigakukun 24-Oct-20 04:25 PM
Rust的なやつ?
Avatar
omochimetaru 24-Oct-20 04:25 PM
左辺値の明示的な型指定をするときに、ResultやPublisherの右側だけ指定して、左側は_にするなどの使い方ができる
16:26
推論器が右辺値から左側だけは推論機できるが右側は推論できない、みたいなときに、
16:26
推論できない方だけをアノテートすればよくて便利
16:27
スレの序盤でドーグとラトナーが良いねって言ってる
16:27
Rustのは知らないからわかんない〜
Avatar
kateinoigakukun 24-Oct-20 04:28 PM
おー、見た感じRustの型パラプレースホルダーと似た感じっぽいですね
16:28
これは良さそう
Avatar
omochimetaru 24-Oct-20 04:28 PM
SwiftUIでややこしい型が出てくるようになったからニーズが高まったらしい
16:28
個人的におもしろいと思ったのはこの機能を作るときに推論エンジンに大きな改修は要らない点
16:29
たんに_を型変数としておいて推論させたら良いだけ!
Avatar
kateinoigakukun 24-Oct-20 04:32 PM
複雑な型パラを省略するという面ではORTと似てるけど全く違うアプローチで面白い
🦀 1
Avatar
tarunon 24-Oct-20 04:40 PM
Javaにもあったような
Avatar
omochimetaru 24-Oct-20 04:41 PM
Javaはそもそも型推論が無いよ(厳密には少しあるけど
Avatar
akira 26-Oct-20 03:23 AM
ビルド時間は伸びないんですかね?
Avatar
omochimetaru 26-Oct-20 03:59 AM
他の型推論と同じで推論箇所が増えると少しは伸びると思います
👌 1
Avatar
akira 26-Oct-20 05:16 AM
やはりそうですよね。仕事で書いてるコードのビルド時間がそれはもう長くて気になってしまいました🙄
Avatar
omochimetaru 26-Oct-20 05:17 AM
でもこの機能は「全く与えない」と「完全に与える」の間の「一部欠けた型を与える」機能を提供するものなので
05:17
使い所を間違えなければデメリットは気にならないと思います、そのときは今まで通り完全な型を書けばよい。 (edited)
05:18
推論が重くない時に楽するための追加機能って感じ。
05:18
仕事で書いてるコードのビルド時間がそれはもう長くて
これ使って型推論が重い部分を調べると良いですよ https://dev.classmethod.jp/articles/investigated_compiletime_swift/
Avatar
akira 26-Oct-20 05:38 AM
たしかに、時と場合で使い分けが重要ですね。情報ありがとうございます。遅いところ調べてみます。
Avatar
omochimetaru 26-Oct-20 05:39 AM
Swiftの推論は、全体的に遅いってことはあんまりなくて、
05:39
特定のパターンでいきなり1000倍重くなるみたいな感じなので
👀 1
05:39
そういう急所を直せると良いです。
Avatar
niw 26-Oct-20 06:06 AM
Int(S_IRUSR) | Int(S_IWUSR) | Int(S_IRGRP) | Int(S_IWGRP) | Int(S_IROTH) | Int(S_IWOTH) を思い出した
Avatar
omochimetaru 26-Oct-20 06:07 AM
それ!
Avatar
kateinoigakukun 26-Oct-20 06:09 AM
オーバーロードされてるやつだ
Avatar
omochimetaru 27-Oct-20 12:10 AM
51でりんたろさんの書いてる _() でinitできる説おもろ
Avatar
rintaro 31-Oct-20 07:35 AM
https://github.com/apple/swift/pull/34523 protocol extension のスタティックメンバーがプロトコルのメタタイプから呼び出せるようになる!
protocol P {} struct S: P {} extension P { static var bar: S { S() } } func foo<T: P>(_: T) {} foo(.bar)
Avatar
omochimetaru 31-Oct-20 07:53 AM
おお?それS見つけられるの凄い気がする
07:54
推論されてるのP.barじゃなくてS.barですよね? (edited)
Avatar
rintaro 31-Oct-20 07:56 AM
P.bar ですね。現状では P.bar はそもそも使えない (Static member 'bar' cannot be used on protocol metatype 'P.Protocol') けどそれが使えるようになって、さらにコンテクストタイプが : P の時に implicit member expression で参照できる (edited)
07:57
Swift's dot shorthand for static factories is wonderful! Unfortunately, it currently requires a concrete type context in order to work. A while ago I pitched an idea for lifting this limitation. It turned out that the original idea in that pitch isn't viable, but the thread ...
Avatar
rintaro 31-Oct-20 08:06 AM
protocol P { associatedtype Arg } struct S: P { typealias Arg = Int } extension P { static func bar(x: Arg) -> S { S() } } func foo<T: P>(_: T) {} foo(.bar(x: 12))
なので、たぶんこれは無理と思います。
Avatar
omochimetaru 31-Oct-20 08:07 AM
ああー、そういうことか
08:08
あれ、でも、.barで見つけられるのって、返り値の型とレシーバの型が同じ時じゃ?
08:10
レシーバはany Pで返り値はSですよね
Avatar
rintaro 31-Oct-20 08:12 AM
class B { static var c: C { C() } } class C: B {} func foo(_: B) {} foo(.c)
ルール的にはレシーバのサブタイプなので、矛盾はしてないかな?
Avatar
omochimetaru 31-Oct-20 08:19 AM
なるほど
08:20
SwiftUIで辛いことになってたStaticMemberのやつができるようになるの大きいですね
Avatar
omochimetaru 31-Oct-20 08:33 AM
Pにstaticメソッド定義できるのネームスペース兼ねられて便利そう inner typeが定義できないか
Avatar
omochimetaru 31-Oct-20 09:12 AM
any Pがstatic methodの実装を持てるなら、any PがPにconformできない理由が一つ減るな
09:14
もはやexistential metatype containerでは無くなってて変な感じ
09:20
P.Typeとの話だからいいのかな?
09:22
P.Protocolとどっちがどっちだったっけ
09:23
このへんかな
🙏 1
Avatar
omochimetaru 31-Oct-20 09:30 AM
P.Protocolにstatic funcが生やせるようになった これによってP.Protocol.self is P.Typeにできない理由が緩和された かな?
Avatar
koher 15-Nov-20 04:35 PM
タプルの Equatable とかのやつ、 AdditiveArithmetic とか Numeric もほしくなる。標準で付けるのは微妙だけど、コンパイラでやらないとできないし・・・。
Avatar
freddi 15-Nov-20 05:36 PM
タプルの要素の型すべてがあるprotocolが準拠してたら、そのタプル自身も準拠するようにしてほしい感があります
17:36
どうなんだろ
Avatar
koher 16-Nov-20 01:08 AM
それはちょっとやりすぎな気も。↓とかできるってことですよね?
protocol P { associatedtype Foo func foo() -> Foo } extension Int: P { func foo() -> Int { self * self } } let a = (2, 3, 5) print(a.foo())
(edited)
Avatar
kateinoigakukun 16-Nov-20 01:09 AM
それはタプル側のfooの実装が自明じゃなさそうですよねー
Avatar
koher 16-Nov-20 01:11 AM
ってか、よく考えたら無理ですね。
protocol P { func foo() -> Int } extension Int: P { func foo() -> Int { self * self } } let a = (2, 3, 5) print(a.foo())
01:11
↑だと (Int, Int, Int).foo()Int を返さないので。
Avatar
freddi 16-Nov-20 02:36 AM
なるほどなあ
Avatar
masakihori 16-Nov-20 02:53 AM
AdditiveArithmeticは横ベクトル同士の自然な加減算があるのでできなくはなさそうですよね
Avatar
omochimetaru 02-Dec-20 06:26 AM
なんかいろいろproposal review走ってるな
06:26
Hello Swift community, The review of SE-0295 "Codable synthesis for enums with associated values"" begins now and runs through Dec 11, 2020. Reviews are an important part of the Swift evolution process. All review feedback should be either on this forum thread or, if you would like to keep your feedback private, directly to the review manager....
06:27
Structure of encoded enums The following enum with associated values enum Command: Codable { case load(key: String) case store(key: String, value: Int) } would be encoded to { "load": { "key": "MyKey" } } and { "store": { "key": "MyKey", "value": 42 } }
06:27
これはいつもめんどくさかったから嬉しい
Avatar
kateinoigakukun 02-Dec-20 06:27 AM
いつも手書きしてるやつだ
Avatar
tarunon 02-Dec-20 06:28 AM
たすかる
Avatar
kateinoigakukun 02-Dec-20 06:29 AM
自分で書くときはこうやりがち
{ "kind": "store", "key": "MyKey", "value": 42 }
Avatar
tarunon 02-Dec-20 06:31 AM
decodeするときに困りますもんね
06:31
その辺よしなにやってくれるのかな(直感的にパフォーマンス悪そう
Avatar
omochimetaru 02-Dec-20 06:32 AM
エンコード方式いろいろ悩んでて
06:33
{ "kind": "store", "value": { "key": "MyKey", "value": 42 } }
Avatar
kateinoigakukun 02-Dec-20 06:33 AM
名前空間汚さないパターンだ
Avatar
omochimetaru 02-Dec-20 06:33 AM
家庭君の書いたやつでやったこともあるし、↑これもやったし、
06:33
このproposalのやつもやった。
06:34
そうね>名前空間
Avatar
kateinoigakukun 02-Dec-20 06:34 AM
proposalの形式だとデコードどうやってますか?
Avatar
omochimetaru 02-Dec-20 06:35 AM
enum Command { struct JSON: Codable { var load: Load? var store: Store? } }
Avatar
kateinoigakukun 02-Dec-20 06:35 AM
なるほど
Avatar
omochimetaru 02-Dec-20 06:35 AM
いったんこういうstructでcodableする。
06:35
これにした理由の一つが、
06:36
TypeScriptの type 文で 相互に受け渡すのが楽だった。
Avatar
kateinoigakukun 02-Dec-20 06:38 AM
type JSON = { load: { key: string } } | { store: { key: string, value: number } }
こういうことですか?
Avatar
omochimetaru 02-Dec-20 06:38 AM
type JSON = { load?: { ... } store?: { ... } }
いやこっち
06:39
たしかにunionでそれでいいのかな
Avatar
kateinoigakukun 02-Dec-20 06:39 AM
いや、このunion取り出せないw
Avatar
omochimetaru 02-Dec-20 06:39 AM
取り出せないっすか?
Avatar
tarunon 02-Dec-20 06:39 AM
これ困るパターンの予感
Avatar
omochimetaru 02-Dec-20 06:39 AM
そのあたり、まだよくわかっていないので、↑のenumになってない書き方をした。
Avatar
tarunon 02-Dec-20 06:40 AM
loadとstoreを逆側にundefinedで定義すると
06:40
!==undefinedで取り出せるようになります (edited)
Avatar
kateinoigakukun 02-Dec-20 06:40 AM
なるほど
Avatar
omochimetaru 02-Dec-20 06:40 AM
全ケースにあるプロパティじゃないと取り出せなくて、それを使ってsmart分岐する感じなのか。
Avatar
kateinoigakukun 02-Dec-20 06:40 AM
でもTSでTagged Unionするなら
Avatar
omochimetaru 02-Dec-20 06:40 AM
いまいちめんどくさいね。kind: string つけたほうが楽やな。
Avatar
tarunon 02-Dec-20 06:40 AM
プロパティがあったり無かったりすると死にがち
Avatar
kateinoigakukun 02-Dec-20 06:40 AM
そうそう
Avatar
omochimetaru 02-Dec-20 06:41 AM
そうするとSwift側でいうとkind付きのcase名プロパティのパターンだね。 (edited)
Avatar
tarunon 02-Dec-20 06:41 AM
コツとしては一通り定義して無ければundefinedにしておく
Avatar
kateinoigakukun 02-Dec-20 06:43 AM
Rustのserdeのデフォルト形式はcase名をキーにするっぽい (edited)
Avatar
omochimetaru 02-Dec-20 06:43 AM
じゃあそれと相互運用しやすい?
Avatar
kateinoigakukun 02-Dec-20 06:44 AM
どうだろう。。
06:45
微妙に互換性がないって言ってた
With the exception of the last case, this solution is closely following the default behavior of the Rust library serde.
Avatar
omochimetaru 02-Dec-20 06:58 AM
ラベルなしの場合に配列になるのね
Avatar
kateinoigakukun 02-Dec-20 07:01 AM
TypeScriptで読みづらそう
Avatar
omochimetaru 02-Dec-20 07:02 AM
TypeScriptと受け渡すなら絶対ラベルはつけておいて
07:02
kindはないから↑で書いたunionじゃないstructの形で受けるかな
Avatar
kateinoigakukun 02-Dec-20 07:03 AM
それしか助からなそう
07:04
でも大抵のユースケースではSwiftからEn/Decodeするだけだからまあいいか…
Avatar
omochimetaru 02-Dec-20 07:05 AM
まあTypeScriptでtypeで受けるのもそもそもサボりかなとは思っている
07:05
ちゃんとencode/decodeを挟まないと
07:06
URI 型とか TypeScript側でただの string になっちゃう。
Avatar
kateinoigakukun 02-Dec-20 07:06 AM
なるほど
Avatar
omochimetaru 02-Dec-20 07:06 AM
User.ID 型とかも。
Avatar
kateinoigakukun 02-Dec-20 07:10 AM
クライアントもSwiftならまるっと解決 (edited)
Avatar
omochimetaru 02-Dec-20 07:10 AM
いやそうなんだよな
Avatar
kateinoigakukun 02-Dec-20 07:14 AM
JSONを構築する側とパースする側が別れてる場合、大抵Swiftはパースする側なのでおもちさんのユースケースはそもそも特殊w いや、全然そんなことなかった。 (edited)
Avatar
omochimetaru 02-Dec-20 07:16 AM
API request送る時はまあ同じかな
Avatar
kateinoigakukun 02-Dec-20 07:17 AM
アプリ書かなさすぎてすっかり忘れてたw
Avatar
omochimetaru 02-Dec-20 07:17 AM
アプリSwift<->サーバサイドSwift はこれのおかげで更にはかどってしまう
Avatar
nanasi 18-Dec-20 09:18 AM
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
09:18
configurationによる制約の方の状況がよくわからない…
Avatar
koher 27-Jan-21 09:39 AM
@koher 僕の理解だと(fとgは) async let a = f() async let b = g() await h(a, b) は並行で await h(await f(), await g()) は直列 後者のような書き方で並行になってほしい 変数/定数に入れたくない
09:40
@masakihori fooとbarがasync funcとして、 await (foo() + bar()) // 並行 (await foo()) + (await bar()) // 直列 とかだと良かったかもですね。ただ、tryとの整合性の問題で今からだと難しそうです。
09:41
try と整合性が取れなくなってしまうけど、わざわざ async let で代入しなくても前者の書き方で並行になってくれたらうれしい?
09:41
try との整合性」というのは https://gist.github.com/koher/ca74ef2c882418f683d06092f4408c3c のような意味です。 (edited)
Avatar
tarunon 27-Jan-21 11:51 AM
他のところで無限に面倒が発生しそう
11:52
これはtsを書いてる感想ですが、向こうは都度await明記しなきゃいけないんで既にだるい。並行並列の機能があったら許せるかと言うとそんな事はないぐらいに怠いので
11:52
1個await書けばその行はオッケー!というのは、大半のユースケースにおいて便利なので、それが壊れるのは微妙かなぁ
11:53
まで書いて、koherさんの真意を確認しにいく (edited)
11:53
あってそう
Avatar
koher 27-Jan-21 01:18 PM
そう考えると async let で 1 回代入挟むくらいがバランス良さそうですね。
Avatar
masakihori 27-Jan-21 02:20 PM
僕はasync/awaitちゃんのことは噂では聞いてたけどお話ししたのはKoherさんに紹介された時が初めてなので、全然分かってないし、誤解とかもいっぱいあると思うのであまり真面目にとらえられると困っちゃいます
😭 1
Avatar
tarunon 27-Jan-21 02:30 PM
ところで私がコンフリクトするな〜と感じたのは、例えばメソッドチェーンでasyncな関数を呼ぶ時で
14:31
async foo() async bar()を呼ぶ時に await hoge.foo().bar() って呼べるので嬉しい、これがコンフリクトしそうだなと
14:32
或いはasyncな関数の引数に別のasyncの結果を渡す場合 await hoge.foo(bar()) みたいなの (edited)
14:33
どちらも結構頻出で、やっぱり所感としては並列より直列の方が多いんですよね。8割ぐらい直列。なので直列の使いやすさを上げるから並列は多少犠牲にする、みたいなのも割と納得だなとは思っています
Avatar
omochimetaru 27-Jan-21 02:37 PM
並列かどうかが明示的な文法として表現されないのは事故(思わぬ並列化による深刻なバグ)につながるのは良くないと思います。
14:38
async let は一見わかりにくいけど、文法として新しいコードの形になっている(これまでの文法として、letの左にasyncは書けない)ので、暴発することはない。 (edited)
Avatar
omochimetaru 27-Jan-21 03:32 PM
await でまとめた式は並列になる」は、async/awaitで新しく導入されるといっても、「await がついてない部分について実行順序の挙動が変わる」のは、 これまでと変化がある部分に対して見た目の変化がないのでわかりづらいと思う。
Avatar
koher 01-Feb-21 05:20 AM
チーム勉強会で async let の話があったので、まとめるとこうなります
Avatar
Avatar
Kishikawa Katsumi
なのでfileprivate使わないなあ、と思いまして。あえてfileprivateじゃないと書けないことってあったっけ?と思って、そうすると、なんで変えたんだっけ?とわからなくなってきました。
koher 01-Feb-21 05:46 AM
これ、この会話の後でたしかに fileprivate 書かなきゃいけないケースってあまりないなと思ってたんですが、↓のようなケースで fileprivate でしか書けなさそうなのを発見しました。
struct S {} private struct T {} private protocol P { func foo() -> T } extension S: P { fileprivate func foo() -> T { T() } }
05:46
Protocol Conformance にアクセスレベル修飾子を書けないという方が本質かもしれませんが・・・。
Avatar
Kishikawa Katsumi 01-Feb-21 06:00 AM
なるほど!おもしろい。
Avatar
koher 04-Feb-21 03:55 AM
Swift 5.2.1 で
let s = readLine()! let a = (0..<2).map(s.dropFirst).count
を実行して 11111111111111111 など 15 or 16 文字以上の文字列を標準入力として与えると -O または -Ounchecked 時に実行時エラーになるそうです。気持ち悪い・・・。 https://twitter.com/_kebo/status/1357011619440599044
以前 AtCoder を Swift で解いているときにぶち当たった特定の環境で特定の条件下で最適化時のみ発生する実行時エラー (Segmentation fault または Illegal instruction) になるコード、どうやら Ubuntu 18.04 の 5.2.1, 5.2.5 では再現するけど 5.3.3 では再現しないことがわかった。
Avatar
Avatar
koher
Swift 5.2.1 で
let s = readLine()! let a = (0..<2).map(s.dropFirst).count
を実行して 11111111111111111 など 15 or 16 文字以上の文字列を標準入力として与えると -O または -Ounchecked 時に実行時エラーになるそうです。気持ち悪い・・・。 https://twitter.com/_kebo/status/1357011619440599044
kebo 04-Feb-21 04:12 AM
そうなんですよね。koher さんがリプライで書いてくださっていた s.dropFirst を変数に束縛するのでも再現しなくなるみたいですし、{ s.dropFirst($0) } のようにクロージャにしても再現しなくなりますし、あとは (ちゃんと記録してませんでしたが) 形を変えて行った時にどこかで二重解放の実行時エラーが出ていたので、s が解放されちゃいけないタイミングで解放されているのかなぁという気がしてます。 かといって withExtendedLifetimes のライフタイムを伸ばしても変わらなかったので、何処かの最適化フェーズに問題があったのではと睨んでます。
04:12
5.3 で再現しなくなったので意識して修正された問題だとしたら apple/swift のコミットログを追うとそれっぽいのがあるかなと思って昨日見ていたんですが、ざっと探したかぎりではそれっぽいのはありませんでしたね...
Avatar
koher 04-Feb-21 04:13 AM
意図せず直っただけならそれはそれで怖いですね・・・。
Avatar
kebo 04-Feb-21 04:13 AM
そうなんですよねぇ...
Avatar
koher 04-Feb-21 04:15 AM
15 or 16 文字以上とか、標準入力じゃないと起こらないとか、変数に一度代入すると起こらないとか、再現条件めちゃくちゃすぎて笑えますね😅
Avatar
tarunon 04-Feb-21 04:31 AM
バグレポ送っときましょ
Avatar
Avatar
tarunon
バグレポ送っときましょ
kebo 04-Feb-21 05:38 AM
過去バージョンでしか再現しないのでバグとして報告して良いものなのか迷ってました。
Avatar
tarunon 04-Feb-21 05:41 AM
把握せずにたまたま治っただけ、だと再発して困るので
05:42
このバージョンで発生していたが新しいバージョンでは治っている、と言うレポートで良いのではないでしょうか
👍 1
Avatar
omochimetaru 04-Feb-21 05:42 AM
確かにバグレポあるとリグレッションテストが追加されて後々も保護されるので良い
Avatar
tarunon 04-Feb-21 05:42 AM
上記の議論を見る限りは結構ディープな奴なので、報告した方が良い
Avatar
kebo 04-Feb-21 06:27 AM
言われてみるとおっしゃる通りですね。bugs.swift.org に報告しようと思います。
Avatar
niw 09-Feb-21 06:01 AM
Protocol extension で mixin するのってわりとやられている手法かな?
Avatar
omochimetaru 09-Feb-21 06:09 AM
やると思う
Avatar
niw 09-Feb-21 06:25 AM
派生を封印してmixinだけでとかはあるか。
Avatar
kebo 12-Feb-21 11:53 PM
この前の問題のバグレポートを出してみました。下手にミニマムな再現コードを用意しようとしたせいで挙動が変わったので結局元の冗長なコードでの実行例も載せることになって見辛いかもしれないですが... https://bugs.swift.org/browse/SR-14202
👏🏼 3
Avatar
Avatar
kebo
この前の問題のバグレポートを出してみました。下手にミニマムな再現コードを用意しようとしたせいで挙動が変わったので結局元の冗長なコードでの実行例も載せることになって見辛いかもしれないですが... https://bugs.swift.org/browse/SR-14202
kebo 16-Feb-21 03:39 AM
結局 5.3 では解決してるからってことでクローズされちゃいましたね。やっぱり古いバージョンでしか再現しないバグは基本的に受け付けてもらえなさそうですね。
😢 2
Avatar
t.ae 22-Feb-21 08:34 AM
https://discord.com/channels/291054398077927425/430242233468452865/813326991989538826 同じコードがmacでは問題なく動くのですが、どこかおかしいところあるでしょうか?
Avatar
Iceman 22-Feb-21 08:39 AM
availableDataが最後空で呼ばれるかどうかがLinuxとMacで違うとか?
Avatar
t.ae 22-Feb-21 08:40 AM
concurrentPerform の引数を1にするとわかりやすいんですが、最後に0のデータが来るかどうかがランダムなんですよね。
08:43
The Foundation Project, providing core utilities, internationalization, and OS independence - apple/swift-corelibs-foundation
Avatar
masakihori 22-Feb-21 09:02 AM
printが出力されてないのはバッファがフラッシュされてないからなので頭に「おまじない」をしてバッファ経由しないようにするとdebugできる?
09:02
// おまじない func print(_ item: String) { fputs(item + "\n", stderr) }
Avatar
Avatar
masakihori
printが出力されてないのはバッファがフラッシュされてないからなので頭に「おまじない」をしてバッファ経由しないようにするとdebugできる?
t.ae 22-Feb-21 09:06 AM
出せました。(字数制限かかるのでstderrの取得部分を省略しました)
Avatar
t.ae 22-Feb-21 09:19 AM
Foundationのコードを真似たらうまく動くようになりました。 SOの回答で availableData が空だったらEOFだからhandlerをnilにするってのを何件かみたんですが、 ドキュメントだと使い方が不明瞭ですね……低レイヤなれてる人なら常識なのかもしれませんが。 https://developer.apple.com/documentation/foundation/filehandle/1412413-readabilityhandler https://developer.apple.com/documentation/foundation/filehandle/1411463-availabledata availableData が空ならEOFというのは合ってそうですが、readabilityHandlerのほうはEOFが来ることを保証していないような気がする。
09:24
readToEnd はmacOS10.15.4からなのにPackage.swiftでは.v10_15 しか指定できない……
Avatar
omochimetaru 22-Feb-21 09:25 AM
#ifの分岐ならできるんじゃ?
09:26
それ以前ではdeprecatedなメソッドを使う
Avatar
omochimetaru 22-Feb-21 09:28 AM
waitが終わったらコールバック外してから改めて吸い出すのかなるほど
Avatar
omochimetaru 10-Mar-21 02:27 AM
Hello! I’m YR Chen from University of Science and Technology of China, majoring in Computer Science. I’ve been using Swift for a long time (mostly in server side) and starting last year I began to contribute codes to Swift and other projects. My works include a simple Swift toolchain management script for Linux, and a forked version of swift-aws...
02:28
スクリプティングに立候補してる人が居る
Avatar
lovee 10-Mar-21 08:16 AM
すごい、日本で言う東工大レベルの人だ 👀
Avatar
omochimetaru 10-Mar-21 08:16 AM
他のOSSの活動とかテンセントの仕事とかも凄い
Avatar
lovee 10-Mar-21 08:23 AM
個人的に米中貿易戦争の飛び火でIT周りが分断されて、所謂「西側スタンダード」と「中国スタンダード」ができてしまって中国からSwiftのコントリビュートが制限されたりするじゃないのってすごい怖かったですけど、とりあえず国立大学でまだSwiftのコントリビュートができるの見てちょっと一安心です 😅
08:23
言っても中国からGitHubまだアクセスできるけどなぜかSpeakerDeckがアクセスできないんですよねw
Avatar
Avatar
lovee
個人的に米中貿易戦争の飛び火でIT周りが分断されて、所謂「西側スタンダード」と「中国スタンダード」ができてしまって中国からSwiftのコントリビュートが制限されたりするじゃないのってすごい怖かったですけど、とりあえず国立大学でまだSwiftのコントリビュートができるの見てちょっと一安心です 😅
omochimetaru 10-Mar-21 08:30 AM
たしかに・・・。中国の人たちがGitHubでテクニカルなコードを結構上げたりしてるし、そういう分断はおきてほしくないです
08:31
TikTokとかあるからなのか、iOSの動画処理のマニアックなの結構中国だったりする
Avatar
lovee 10-Mar-21 08:32 AM
多分それだけじゃないと思います;まあ国際的に有名なのはTikTokですが、中国国内でも他に快手とか西瓜とかめっちゃ色々あります
08:35
しかも中国5Gになった今でも未だに従量課金ですからね…(単価はだいぶ安くなってはいますが)やはりトラフィック気にする人が多いから、多分ライブストリーミングの圧縮アルゴリズムとかめっちゃ強そう
Avatar
omochimetaru 10-Mar-21 08:48 AM
なるほどー
Avatar
niw 11-Mar-21 03:01 AM
SpeakerDeck は GitHub じゃなくなったからなあ (edited)
Avatar
lovee 11-Mar-21 08:00 AM
まじで!?
Avatar
niw 12-Mar-21 03:00 AM
https://twitter.com/niw/status/1307488577106796544 そう、知らなくて、slide shareとか関係あんのかなあって言ったら作った本人から返事来た
今更だけど、@speakerdeck が売却されていたことを知った。Slide Share が Microsoft だからとかなのか。
👀 1
Avatar
tarunon 16-Mar-21 11:41 AM
👀 1
11:42
議論がとっ散らかるとよくないのでサブタイプが存在することによって発生する大きな問題点を2つ、整理します。
11:45
まず1つ目がサブタイプであるにも関わらず、実体が異なってしまうという点
var s = 1 var a: Int = s var b: Int? = s
のaとbが異なるということですね。クラスサブクラス、あるいはExistentialと具体型の関係なら、これは同じものを指すわけです。(Existentialは厳密には異なるが省略)
var s = Cat() var a: Animal = s var b: Cat = s
この結果発生する問題として、 実態が異なっているということを知っているユーザーと知らないユーザーとの間で、期待する挙動に差が出てきます。例えば
11:46
https://discord.com/channels/291054398077927425/375206337937801216/806433474579005440 最近発生したバグとされるこの挙動。 AnyHashableにInt?の値を入れた時に、Intを入れた時と異なってしまう、というバグ
11:46
でもこれは、「いやいやそうは言っても .some(1)1 は別でしょ」っていう理解のユーザーからは、AnyHashableの値が異なることこそが期待される挙動なはずです。
11:48
このOptionalであるか否かが同一かどうかというのは、文脈によっても期待される挙動が異なるので、ケースバイケースでコンパイラの挙動が変わることが期待されてしまう。
11:48
片方を立てれば片方は立たなくなる、という問題の根源になりえるわけです。
11:48
次 2つ目、サブタイプのルールづけに優先順位が必要という話。
11:51
これは結構私は方々でぶーを垂れてるので知ってるかもですが、 TがT?のサブタイプである UがTのサブタイプであるならばU?はT?のサブタイプである この2点がSwiftでは許可されています。で、下のコードはコンパイルが通る。
var s = Cat() var a: Animal = s // CatとAnimalのサブタイプ関係が成り立つことを示す var b: Cat? = s var c: Animal? = b
U?はT?のサブタイプ、は具体のコードとしては、 UITableViewController? な変数が UIViewController? に渡せる、というのが頻出すると思います。
(edited)
11:52
もちろんOptionalは実体は別なので、暗黙的な変換が挟まるわけですが、どうなっているかというと
11:53
var s = Cat() var a: Animal = s // CatとAnimalのサブタイプ関係が成り立つことを示す var b: Cat? = .some(s) var c: Animal? = b.map { $0 as Animal }
mapのところは本当は違うと思うんですが、まあ雑にこんな感じ。
(edited)
11:54
じゃあここに一行付け加えて、これはどうあるべきでしょうか。というのが問題になります。
var d: Cat?? = b // b: Cat?
11:55
解釈としては2通りあって、
1. オプショナルのサブタイプなので.someでラップする 2. CatはCat?のサブタイプなのだから、.mapでOK
11:57
今このコードだと、Cat?は.someなので結果は同じなんですが、Cat?が.noneだと、1,2のどちらを採用するかで結果が変わります。
11:58
// 1. var d1 = .some(b) // 見たまま.some(.none)になります // 2. var d2 = b.map { $0 as Cat? } // これは.noneになります
じゃあこれがどういう問題を引き起こしたかというと
11:59
過去のSwiftではコンテキストの差によって2.の変換が採用されていた時代がありました。
12:01
Avatar
Iceman 16-Mar-21 12:01 PM
なるほど
Avatar
tarunon 16-Mar-21 12:02 PM
以上2点がメジャーな問題だと私が感じている点
12:02
期待される挙動が人や文脈によって異なる、というのが問題という議論ですね。
Avatar
Iceman 16-Mar-21 12:04 PM
どちらも確かにと思うところがあるし、2つ目はどうなるんだっけと悩んだ記憶もありますね
12:06
本質的に実体が異なるものを文法とコンパイラによってほとんどWrappedとして扱えるように隠蔽していた部分でエッジケースで齟齬が出るのはしょうがないという感じもしますね
12:08
Optionalが仮にKotlinやTSのようなUnionだったらどう不便になるんだろう?
12:08
そもそも値型が扱えないとかの問題になるのかな
Avatar
tarunon 16-Mar-21 12:13 PM
Unionの場合はOptionalのOptionalが表現できなくなるので
12:13
まあそれはそれで困ることがある
12:13
例えばGenericsにOptionalを渡すことは出来ないはず
Avatar
Iceman 16-Mar-21 12:15 PM
Optionalのネストは我慢できるような気がしてますが、型パラにOptional渡せないのは厳しそう
Avatar
Avatar
tarunon
これは結構私は方々でぶーを垂れてるので知ってるかもですが、 TがT?のサブタイプである UがTのサブタイプであるならばU?はT?のサブタイプである この2点がSwiftでは許可されています。で、下のコードはコンパイルが通る。
var s = Cat() var a: Animal = s // CatとAnimalのサブタイプ関係が成り立つことを示す var b: Cat? = s var c: Animal? = b
U?はT?のサブタイプ、は具体のコードとしては、 UITableViewController? な変数が UIViewController? に渡せる、というのが頻出すると思います。
(edited)
omochimetaru 16-Mar-21 12:19 PM
ここ UIView? の間違い?
12:23
暗黙の型変換だと、変換元の型から変換先への型への妥当な変換方法が複数存在した場合に、どちらを選択しているのかがわからず、場合によってはその違いによって振る舞いが変わるケースが出てくる、ということだなあ
12:24
暗黙の型変換が無ければ陽に記述されるから曖昧性はないし、一貫して区別できない同じものとみなすアプローチでも曖昧性は無いと・・・
Avatar
Avatar
omochimetaru
ここ UIView? の間違い?
tarunon 16-Mar-21 12:25 PM
なおした、tx
Avatar
Avatar
tarunon
なおした、tx
omochimetaru 16-Mar-21 12:25 PM
よくまとまってるしgistかzenかなんかに貼っておくと良いのでは
Avatar
tarunon 16-Mar-21 12:26 PM
置くわ〜
12:26
Unionだったらどうなの、とかサブタイプのどれを諦めたら何が起きるのみたいなのまでまとめて
Avatar
Iceman 16-Mar-21 12:26 PM
この文章をほとんど一筆書きしてるのがすごい
Avatar
tarunon 16-Mar-21 12:26 PM
置いとくかな
12:26
アイスマンはリアタイで見てたからねw
Avatar
tarunon 24-Mar-21 04:06 PM
🤩 1
Avatar
omochimetaru 24-Mar-21 05:30 PM
結構前からあった文書で、そろそろレビューに進めようって話が出たところか
Avatar
omochimetaru 24-Mar-21 05:49 PM
プロポーザルの英語が難しくて自信ないけど、実装の方のテストも合わせて見た感じでは (edited)
17:50
今まで Existential type として使えないようなprotocolでも使えるようにするが、
17:50
contravariant Self と associatedtype が絡んでるメンバは呼び出せないという制限付きになる
17:50
という話っぽい
Avatar
tarunon 24-Mar-21 05:51 PM
ウーンまあしょうがないか
Avatar
omochimetaru 24-Mar-21 05:51 PM
protocol IntCollection: RangeReplaceableCollection where Self.Element == Int {} こういうふうにassociatedtypeを埋めて再定義してやれば使えるけど
17:51
汎用的に any Collection<Element = Int> みたいにパラメータを埋められる、
17:52
いわゆる generalized existential ではないっぽいね
17:53
この範囲であれば実は現状でも、
17:53
問題が起こらないメンバだけ集めた別名のプロトコルが定義してあれば、できるんだよな
17:53
後付はできないけど
Avatar
tarunon 24-Mar-21 05:54 PM
割とそれはやった記憶がある
17:54
ワークアラウンド無しに直接書けるようにはなるものの
17:54
そこまで大きく表現できるコードは変わらなさそうだなぁ
Avatar
omochimetaru 24-Mar-21 05:54 PM
そういう感じだね。できるようになる事もあるけど、
17:55
肝心のtype erasureを手書きする時のユースケースに関してはあまり役に立たなそう
Avatar
koher 06-Apr-21 09:43 AM
Swift Collections の話、 OrderedSet/Dictionary もいいけど SortedSet/Dictionary も欲しくないですか?ツリーで実装されてて、各種操作が O(log N) で、イテレートしたらソート済で全要素 O(N) で取得できるやつ。
Avatar
omochimetaru 06-Apr-21 09:47 AM
そっちは欲しかったことないけどたまに使いたい時がありそうですね
09:48
OrderedDictionaryは HTTP Cookieの値とかJSON objectの値を表現するときにわりとよく出てくる
Avatar
koher 06-Apr-21 10:08 AM
single element なタプルってラベル付けられないのか。 @swift-5.3.3
let a: (foo: Int) a = (foo: 42) print(a)
Avatar
swift53 BOT 06-Apr-21 10:08 AM
exit status: 1 with stderr:
<stdin>:1:9: error: cannot create a single-element tuple with an element label let a: (foo: Int) ^~~~~ <stdin>:2:5: error: cannot assign value of type '(foo: Int)' to type 'Int' a = (foo: 42) ^~~~~~~~~
Avatar
tarunon 06-Apr-21 10:09 AM
TSやってると欲しいなーってなることがチョイチョイある
Avatar
omochimetaru 06-Apr-21 10:09 AM
ラベル付きの方を禁止すると
10:09
ラベルなしの方はただの丸括弧式のように見えるようにもなって
10:10
シングルタプルは存在しない世界になる 気がする
10:11
型の場合も (T)T が同じものですよね
Avatar
koher 06-Apr-21 10:11 AM
single element なタプルはただの値と等価だけど存在してるんじゃないの?
let a: (Int) = 42
Avatar
omochimetaru 06-Apr-21 10:11 AM
let a: (Int) = 42 print(type(of: a)) // Int
Avatar
koher 06-Apr-21 10:11 AM
single element なタプルが存在しないんじゃなくて、ただの値が single element なタプルという理解。
Avatar
omochimetaru 06-Apr-21 10:12 AM
let f: () -> (Int) = { 0 } print(type(of: f)) // () -> Int
10:13
single elementなタプルは存在しないんじゃないかしら?まあ、Tと(T)が同じものなのだ、って解釈なら意味は同じですね
Avatar
koher 06-Apr-21 10:15 AM
うん、 T(T) は同じものですべての値は single element なタプルだと思ってる。内部的な扱いは別として、概念的に。
10:16
ラベル付けられて↓みたいに書けたら便利そう。
func foo() -> (isUpdated: Bool) { ... }
Avatar
omochimetaru 06-Apr-21 10:17 AM
それはありますね〜
10:17
Bool返すときにそのBoolの意味が表現できなくて困る
Avatar
koher 06-Apr-21 10:46 AM
コレクションのインデックスと要素をペアにして取得するためのメソッドってありますっけ? enumerated (オフセットしか返してくれない)ではなく。見たところ見当たらない。 @swift-5.3.3
let a: ArraySlice<Int> = [0, 1, 2, 3].dropFirst(2) for (i, x) in a.enumerated() { print(i, x) } for i in a.indices { print(i) }
Avatar
swift53 BOT 06-Apr-21 10:46 AM
0 2 1 3 2 3
Avatar
koher 06-Apr-21 10:46 AM
0 2, 1 3 ではなく 2 2, 3 3 を得たい。
Avatar
Iceman 06-Apr-21 10:52 AM
Swift Algorithms is an open-source package of sequence and collection algorithms, along with their related types. - apple/swift-algorithms
10:52
これですかね?
Avatar
koher 06-Apr-21 10:59 AM
お、これっぽいです!ありがとうございます。 (edited)
10:59
Swift Algorithms にあるのかぁ。
11:00
This is essentially equivalent to zip(x.indices, x)
なるほど。
Avatar
omochimetaru 06-Apr-21 11:06 AM
enumeratedはそうか、元のコンテナに渡せるIndexじゃあないんですね
Avatar
koher 06-Apr-21 01:47 PM
そうなんです。 ArraySlice 使ってるときとか使いづらくて・・・。でも zip(x.indices, x) で良さそうですね。
Avatar
omochimetaru 07-Apr-21 04:44 AM
.indexed() のほうがzipに同じx が2回書かれている事を読み取らなくていいので、filterでかけるときはreduceを使わなくて良いのと同じで、 indexedのほうが良いと思います 名前も自明だし。
Avatar
koher 07-Apr-21 06:36 AM
ああ、 indexed() がいいのはもちろんとして、わざわざそのために Swift Algorithms を入れたくないようなケースでは、ですね。
Avatar
omochimetaru 07-Apr-21 06:37 AM
依存の追加はまあ微妙ですねえ・・・
06:37
こういうのってほんの一箇所だけほしいみたいになりがちで
06:37
パッケージでドカンと入れても5%も使わない
Avatar
Kishikawa Katsumi 07-Apr-21 06:38 AM
CocoaPodsでいうサブモジュールみたいな概念が入ってくるかな。今でもSPMにあるような気もするけど。
Avatar
omochimetaru 07-Apr-21 06:38 AM
swift-collectionsとかswift-numericは、中でさらにわけてありますね。
06:38
パッケージの中からライブラリを選んで入れるような感じになっている
Avatar
Kishikawa Katsumi 07-Apr-21 06:38 AM
あ、それはいいですね。
06:39
最終的にはまとめてドンっと入れてリンクするときに使ってるものだけってやってくれると理想的かなあ。
06:40
あ、それが家庭さんがWASMでやってたLTOってやつか。
Avatar
omochimetaru 07-Apr-21 06:40 AM
そうですね。バイナリサイズ的にはそうなんですが、
06:41
実践的には、バージョンアップ時に使ってないところの影響を確認するとかも必要な気がする
06:41
ライブラリのバージョンアップでXXの仕様が代わりました〜ってのが使ってない95%のところで起きてても
06:41
使ってない95%のところであることを確認したりしないといけない
Avatar
Kishikawa Katsumi 07-Apr-21 06:43 AM
確かに、その観点だと細かく導入できるのはメリットがありますね。
Avatar
omochimetaru 07-Apr-21 06:44 AM
そういうのまで自動だったら、とりあえずドンしても気にならなそうかな・・・
06:45
semverを信じられれば楽になりますね。
Avatar
Kishikawa Katsumi 07-Apr-21 06:47 AM
SemVerはまあ無理ですよね。ソフトウェアがうまくやってくれる仕組みはそんな遠くない将来できると思う。
Avatar
niw 07-Apr-21 07:16 AM
ライブラリオーサーとしては semver 厳しい
07:16
major だけぽんぽんあげると楽っていう抜け道もあるし...
07:17
ユーザーとしては信じられるならラクですよね。
07:17
Goのmoduleがその辺かしこく解決してて、
07:17
結果すさまじく複雑になってます
Avatar
omochimetaru 07-Apr-21 07:17 AM
majorポンアゲされたら振り出しに戻る
Avatar
kateinoigakukun 14-Apr-21 02:22 AM
Hello Swift community, The review of SE-0310 "Effectful Read-only Properties"" begins now and runs through April 27, 2021. Reviews are an important part of the Swift evolution process. All review feedback should be either on this forum thread or, if you would like to keep your feedback private, directly to the review manager. When emailing the...
Avatar
koher 14-Apr-21 02:39 AM
-> の前に async が要りそう。
extension BankAccount { func meetsTransactionLimit(_ limit: Amount) -> Bool { return try! await self.lastTransaction.amount < limit // ^~~~~~~~~~~~~~~~ // this access is async & throws } }
Avatar
omochimetaru 20-Apr-21 02:14 PM
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
14:14
unsafelyUnwrapped の利用例こんなところで見つけた
14:15
However, in optimized builds (-O), no check is performed to ensure that the current instance actually has a value.
-O でさえチェックコストが消えるらしい。
Avatar
koher 28-Apr-21 08:56 AM
最近よく↓みたいなのほしいなぁと思うんですが、便利そうじゃないですか?
extension Sequence { func sorted<T>(by keyPath: KeyPath<Element, T>) -> [Element] where T: Comparable { sorted(by: { $0[keyPath: keyPath] < $1[keyPath: keyPath] }) } }
// ↓みたいにして使う users.sorted(by: \.age)
Avatar
omochimetaru 28-Apr-21 08:57 AM
Foundationにあった気がする。Rubyにもありますね。
08:59
SQL文のORDER句みたいに第二、第三キーも指定していける(asc/descもある)
Avatar
tarunon 28-Apr-21 09:00 AM
NSSortDescriptorだ、懐かしい
09:00
そういえばkeyPathからstring取れるようにしろ!はどうなったんだろ
Avatar
koher 28-Apr-21 09:07 AM
なるほど。 keyPaths: KeyPath<Element, T>... を受け取るようにしようとしたけど、 Swift の Comparable は同値判定がないから Equatable もないとだめだな。
09:08
あれ? Comparable は Equatable ?
Avatar
omochimetaru 28-Apr-21 09:08 AM
a == b!(a < b) && !(b<a) ですよ
Avatar
koher 28-Apr-21 09:09 AM
Comparable: Equatable だった。これは知らなかった。
Avatar
omochimetaru 28-Apr-21 09:09 AM
< だけあれば == を含む 5種類の比較は全部構成できます (edited)
👍 1
Avatar
koher 28-Apr-21 09:11 AM
extension Sequence { func sorted<T>(by keyPaths: KeyPath<Element, T>...) -> [Element] where T: Comparable { sorted(by: { for keyPath in keyPaths { let l = $0[keyPath: keyPath] let r = $1[keyPath: keyPath] if l < r { return true } else if l > r { return false } } return false }) } }
09:12
asc, desc は reversed あるからなくてもいい気がする。
Avatar
omochimetaru 28-Apr-21 09:13 AM
第二キーがdescとかは、reversedにはエンコードできないと思う
09:13
第1キーが同一なグループの中での話になるので。
Avatar
Iceman 28-Apr-21 09:13 AM
これだとTが異なるときに複数keypathで使えなさそう?
Avatar
koher 28-Apr-21 09:14 AM
あ、ほんとだ。
09:14
うーん、可変長ジェネリクスが待たれる・・・。
09:14
N個オーバーロードするのは萎えるな。だから標準にないのか。
Avatar
Avatar
omochimetaru
第二キーがdescとかは、reversedにはエンコードできないと思う
koher 28-Apr-21 09:15 AM
たしかに。
Avatar
omochimetaru 28-Apr-21 09:15 AM
Comparatorを受け取るComparatorとして抽象化すれば
09:15
第一キーでソートするComparatorが
09:15
第二キーでソートするComparatorを
09:15
型パラメータとして保持する構造にできそう。
09:15
雪だるまジェネリクスでいける気がする。
Avatar
Avatar
omochimetaru
雪だるまジェネリクスでいける気がする。
koher 28-Apr-21 09:17 AM
実現はできそうだけど使い勝手変わらない?
Avatar
omochimetaru 28-Apr-21 09:17 AM
メソッドチェーンしていくような感じになりそう。
Avatar
tarunon 28-Apr-21 09:17 AM
雪だるま型パラ+書き味ならResultBuilder使いどころだけど微妙な気もするな
09:18
AnyKeyPath配列で良い気もするよ
Avatar
omochimetaru 28-Apr-21 09:18 AM
array.sort(Comparators.key(\.a).key(\.b, .desc))
Avatar
tarunon 28-Apr-21 09:19 AM
chainingでもいいか
09:19
たしかに
Avatar
koher 28-Apr-21 09:19 AM
可変長ジェネリクスあっても T...KeyPath<Element, T>...... が対応することを示さないといけなくて構文上きついなぁ。
extension Sequence { func sorted<T...>(by keyPaths: KeyPath<Element, T>...) -> [Element] where T: Comparable { // 省略 } }
Avatar
rintaro 29-Apr-21 04:15 AM
private func _cmp<Value: Comparable>(_ lhs: Value, _ rhs: Value) -> Bool? { lhs == rhs ? nil : lhs < rhs } private func _cmp<Root, Value: Comparable>( _ lhs: Root, _ rhs: Root, on keyPath: KeyPath<Root, Value> ) -> Bool? { _cmp(lhs[keyPath: keyPath], rhs[keyPath: keyPath]) }
こういうの用意しておいて
array.sorted { _cmp($0, $1, on: \.prop1) ?? _cmp($0, $1, on: \.prop2.other) ?? false }
でいいや、って最近なりました。
Avatar
koher 29-Apr-21 04:39 AM
なるほど・・・。
04:42
実用上 80% くらいは単一のキーで済むから、 func sorted<T>(by keyPath: KeyPath<Element, T>) と、複数のキーの場合は都度クロージャ式を実装でもいい気も・・・。 3 キーくらいまで extension 用意しておけば 98% くらいカバーできそう。
Avatar
omochimetaru 29-Apr-21 04:43 AM
Bool?にして??で合成するの面白い
Avatar
koher 30-Apr-21 10:03 AM
struct Foo<Bar> { struct Baz {} }
があるときに、 Foo<Bar>.Baz であってほしいときと Foo.Baz であってほしいときないですか?単に Foo に関連する型をネームスペースとして Foo. にまとめたいときに Foo<Bar>.Baz になると鬱陶しいことが。
Avatar
tarunon 30-Apr-21 10:03 AM
そういう場合はProtocol以下にNamespace作りたい時と同じように、Foos を作って解消するのが良さそう
Avatar
koher 30-Apr-21 10:05 AM
Avatar
Kishikawa Katsumi 30-Apr-21 10:06 AM
ほとんど Foo.Baz の方がほしいかなあ。
Avatar
Avatar
Kishikawa Katsumi
ほとんど Foo.Baz の方がほしいかなあ。
koher 30-Apr-21 10:07 AM
いやそうなんですよね。8割くらいそっちがほしいから鬱陶しいなってなる。
Avatar
omochimetaru 30-Apr-21 10:07 AM
インナータイプがアウタータイプのコンクリートな型パラメータに束縛されてるの
10:08
Javaの感覚があったから最初は違和感あったけど、
10:08
このswiftのルールの方が綺麗に感じるようになった
Avatar
tarunon 30-Apr-21 10:09 AM
実際はBarにアクセス出来ちゃいますもんね
Avatar
kateinoigakukun 30-Apr-21 10:09 AM
BarがBazの定義の中で使われてないときだけ、Foo.Bazを書けるようにする、みたいな議論あるのかな (edited)
Avatar
Avatar
omochimetaru
このswiftのルールの方が綺麗に感じるようになった
koher 30-Apr-21 10:09 AM
理論上は正しいと思うんだけど、ネームスペースとして型を使うのと相性が良くない。
Avatar
omochimetaru 30-Apr-21 10:09 AM
とはいえ分離されていて欲しい時もあるのはそうなので、複数形ネームスペースに逃してる
Avatar
tarunon 30-Apr-21 10:09 AM
書けるようにする
使われてないことを保証するのがしんどいと思う
Avatar
omochimetaru 30-Apr-21 10:09 AM
型はネームスペースじゃないからしょうがない
Avatar
tarunon 30-Apr-21 10:09 AM
実装も含めて全部見ないといけない
Avatar
kateinoigakukun 30-Apr-21 10:10 AM
そうなんですよね、declだけみるだと足りない
Avatar
tarunon 30-Apr-21 10:10 AM
途中の実装に一瞬Barが出てきて、型として露出してないとか普通に成り立つんで
Avatar
Avatar
kateinoigakukun
BarがBazの定義の中で使われてないときだけ、Foo.Bazを書けるようにする、みたいな議論あるのかな (edited)
koher 30-Apr-21 10:10 AM
それはStructural SubtypingっぽくてSwiftらしくないような。この場合はサブタイピングじゃないけど構造から型を決めるという点が。
Avatar
tarunon 30-Apr-21 10:10 AM
無理ですね
Avatar
omochimetaru 30-Apr-21 10:11 AM
typescriptは、同じ名前のネームスペースと型を定義できた気がする
Avatar
koher 30-Apr-21 10:11 AM
BazがBarを使っていないのがたまたまか判断できないから、ちょっと実装を変えるだけで型が変わってしまう可能性があって厳しそう。
Avatar
Avatar
omochimetaru
typescriptは、同じ名前のネームスペースと型を定義できた気がする
kateinoigakukun 30-Apr-21 10:12 AM
そうすると正攻法はこれかなぁ
Avatar
omochimetaru 30-Apr-21 10:12 AM
Swiftもネームスペース構文を別に用意するのが綺麗な気はする
Avatar
koher 30-Apr-21 10:13 AM
そうだね。 enum でネームスペースにしてるのとか微妙だし。
Avatar
omochimetaru 30-Apr-21 10:14 AM
だいたい型でできるからこれでよくね?のままになってる感じがする
10:15
ただまあ同名の型とネームスペースを許すと推論器の負担がまた増えそうだけどw
Avatar
koher 30-Apr-21 10:15 AM
Swiftが発表されたときの、Swiftの機能が羅列されたスライドで "Namespaces" って書かれてたのに・・・。あれはモジュールの意味だったんだろうけど。
Avatar
omochimetaru 30-Apr-21 10:15 AM
あれはモジュールでしたね。
Avatar
Kishikawa Katsumi 30-Apr-21 10:15 AM
struct Foo<Bar> { } struct Foo.Baz { }
こういうふうに書けたらいいんちゃうかと思ったことある。
Avatar
koher 30-Apr-21 10:16 AM
なるほど。
Avatar
omochimetaru 30-Apr-21 10:16 AM
モジュールも本来入れ子を作れる仕組みだからそっちを進めるのもありえるのかな
Avatar
koher 30-Apr-21 10:16 AM
たしかに extension はそうですしね。
10:16
Foo<Bar>.BazFoo.Baz の共存とかあり得る?もっと言えば nested type と namespace で名前が被るとどうなる??
Avatar
Avatar
Kishikawa Katsumi
struct Foo<Bar> { } struct Foo.Baz { }
こういうふうに書けたらいいんちゃうかと思ったことある。
omochimetaru 30-Apr-21 10:17 AM
これはわかりやすいですね。
Avatar
tarunon 30-Apr-21 10:33 AM
xcworkspace/xcodeprojの中でモジュールがシュッと宣言できてライトウェイトな感じになるのが一番良い解決な気はしますね
Avatar
omochimetaru 13-May-21 11:59 PM
Hello everyone, We separated out and updated the async let proposal with the latest semantics and spelling details. This is the first pitch of the feature as a stand-alone thing, it was previously pitched as part of structured concurrency pitch #1, and pitch #2 and was separated out later on as it's a feature large enough to deserve it's own d...
00:00
async let 単体のピッチが立った。ちゃんとした提案書もついてる。 提案書の中で、 TaskGroup.spawnTaskGroup.async に変更されていて、 spawn let ではなく async let なのはそれに揃ってるという事になっている。
Avatar
omochimetaru 14-May-21 12:34 AM
await しなければ静的エラーだろうって話を以前したけど、 この文書だと、スコープ脱出時にキャンセルしてキャンセル完了を待機するって仕様になっている。 1つ目のタスクの結果を見て2つ目のタスクの結果を捨てるみたいなフローを考慮したっぽい。 (edited)
Avatar
omochimetaru 14-May-21 02:09 AM
spawn の方がいいんじゃないかって意見を書き込んだら、 async let になった経緯として、 複数のAPIを async に統一するって方針の議論がある事を教えてもらった。
Avatar
koher 27-May-21 10:47 AM
↓みたいなパターン書くことになるケース結構多くないですか?
let foo: Foo if let f = self.foo { foo = f } else { foo = Foo(...) self.foo = foo }
Avatar
omochimetaru 27-May-21 10:47 AM
まあまあ多い
Avatar
koher 27-May-21 10:47 AM
↓こういうのあると良さそう?
let foo: Foo = self.foo.value(default: Foo(...))
10:48
Dictionarydictionary[key, default: value] += 1 みたいなノリで。
Avatar
omochimetaru 27-May-21 10:49 AM
僕はこう書いてます
let foo = self.foo.ensure { Foo(...) }
@discardableResult public mutating func ensure(_ f: () throws -> Wrapped) rethrows -> Wrapped { if let x = self { return x } let x = try f() self = x return x }
Avatar
koher 27-May-21 10:50 AM
そこのクロージャは @autoclosure でいい気がする。 (edited)
10:50
↑ koherさん欲しいって言ってますね。
Avatar
koher 27-May-21 10:51 AM
この会話まったく覚えてないなw
Avatar
omochimetaru 27-May-21 10:51 AM
いや、普通にFooの初期化に数行かかることもあるので、クロージャで便利ですよ
Avatar
koher 27-May-21 10:52 AM
初期化数段は前の行でもいいかと思ったけど、 nil のときだけ初期化だからやっぱクロージャがいいか。
10:53
昔は思い付かなかったみたいなのに今は近い案を思いついたから成長してるな🙂
10:53
この ensure 普通に標準ライブラリにほしいね。
Avatar
omochimetaru 27-May-21 10:54 AM
Contribute to omochi/WeaselRoll development by creating an account on GitHub.
Avatar
koher 27-May-21 10:54 AM
toggle, subscript[_:default:], reduce(into:_) とかの仲間としていけるんじゃないかなぁ。
Avatar
omochimetaru 27-May-21 10:54 AM
自分はライブラリにして使ってます
10:55
public mutating func consume<R>(_ f: (Wrapped) throws -> R) rethrows -> R? { guard let x = self else { return nil } self = nil return try f(x) }
10:55
対のconsumeとセットできれいに収まることがまあまあある
10:55
self.foo.consume { $0.shutdown() }
Avatar
koher 27-May-21 10:55 AM
なるほど。
10:56
まあ、そっちは分岐で普通に書けるんよね。
if let foo = self.foo { foo.shutdown() self.foo = nil }
10:59
3 年前も同じこと言ってた。成長してなかった。
Booltoggle が通ったことを考えるとこれもいけるのでは?
https://discord.com/channels/291054398077927425/306995750418513920/460706985222995979
11:00
↓これも。
Dictionarysubscript(_:default:) は同じじゃないですか?
11:00
rintaroさん、Proposal出してみてほしいなぁ。
Avatar
omochimetaru 27-May-21 11:04 AM
まあconsumeはフローは簡単だからそんなに大変ではないけど foo って4回書くのが1回で済むので結構使ってます。
Avatar
niw 04-Jun-21 06:26 PM
struct で不必要に let つかうのやめようぜっていったら猛攻をくらった...
Avatar
koher 04-Jun-21 07:27 PM
記事について この記事は potatotips#39 という勉強会で発表した内容を再掲したものです。スライドの画像と、喋った言葉を載せました。 以下スライド それではこれから、Swift の struct の st...
Avatar
niw 04-Jun-21 07:28 PM
おもちさんのかな
19:28
それです
19:28
とりあえず let 原理主義ってのがあるのがわかった気がする
Avatar
koher 04-Jun-21 07:30 PM
手軽に変えられたくないプロパティに let を使いたくなる気持ちはわからんでもないですけどね。原理的に変えられることと、変えるための手軽な手段が存在することは異なるので。ただ、境界があいまいになるので、突き詰めると↑になっちゃうんですよね・・・。
19:31
利用時に let にすれば十分なケースまでプロパティ側を全部 let にするのは許容しづらいですが。
Avatar
niw 04-Jun-21 07:32 PM
JSONレスポンスを表現するstructのプロパティが変わってしまうのは危険だからletがいい
19:33
という意見があったんだけどそれは... 利用側の問題では...
19:33
なんかちょっと責任逃れしたいてきな気持ちもあるのかも
19:33
(自分の書いた struct は変えられないから安心、的な) (edited)
Avatar
Kishikawa Katsumi 04-Jun-21 07:35 PM
レスポンスのStructはPOSTにも使うことあるからvarにしてくれた方が便利とか思いますね。
Avatar
niw 04-Jun-21 07:36 PM
あと聞いたのは、letじゃダメな理由は何か、ってやつですね
Avatar
koher 04-Jun-21 07:39 PM
JSONレスポンスを表現するstructのプロパティが変わってしまうのは危険だからletがいい という意見があったんだけどそれは... 利用側の問題では...
これは利用側が let で宣言してれば問題ないと思いますね。
Avatar
niw 04-Jun-21 07:40 PM
ですね。
Avatar
koher 04-Jun-21 07:41 PM
それに [User] がレスポンスで返ってくるようなケースを考えると、 Arraymutaing func を持つので、それは問題にならないの?って話になりますしね。それが許容できるなら(利用側で let users: [User] で問題ないなら) struct のプロパティも var でいいでしょという。
Avatar
niw 04-Jun-21 07:56 PM
あー、それはいいポイント
19:56
[]がルートであることは少なそうだけど。
19:56
一貫性はかける。
Avatar
tarunon 04-Jun-21 11:46 PM
Userが例えばDB由来の値として仮定するなら、user_idはどんな状況でも可変にしたら変なので、そこだけletにするというのは頷けます。
23:46
それ以外はvarにしないことのデメリットが大きすぎる
Avatar
omochimetaru 04-Jun-21 11:48 PM
structのletを許容できる状況は、他のプロパティから依存して決まるプロパティだけだと思ってます
23:48
プロパティ一個だけ書き換えた時にその型が持つ制約をやぶるのをletプロパティで防ぐ。 (edited)
23:48
それ以外は、型全体をletで使えば変更できない版として使えるので元定義はvarだけでオッケー
Avatar
niw 04-Jun-21 11:50 PM
なんか、やっぱり var で使われる恐怖みたいなのを言う人が多かったかな
Avatar
tarunon 04-Jun-21 11:50 PM
主なデメリットは、 1. letはトップレベルに置くだけでその役割を果たせる 2. フィールドを変更するときの手間が大きくなる(swiftにおいてmutatingは値型の性質によりselfを返す関数と同等と見なせる) (edited)
Avatar
niw 04-Jun-21 11:50 PM
その制約を破る、かどうかを判断するのが面倒
23:50
みたいな意見もあった
23:51
(まあ面倒とは言わないけれど(安全じゃないとか)、まあ面倒ってことだと思う)
Avatar
omochimetaru 04-Jun-21 11:52 PM
JSONで帰って来た値を表示する状況で、プロパティがvarだったからって書き換えて違うもの表示する人間を想定するの、何も作れなくないか?
23:52
そんなことしないだろ。
😂 1
Avatar
tarunon 04-Jun-21 11:53 PM
そういうことする人は、別にletにしたとしてもinitしなおすと思うけど
😂 1
Avatar
Avatar
niw
みたいな意見もあった
omochimetaru 04-Jun-21 11:53 PM
判断保留で安全側に倒すのは、一理ありますね。不便だけどレスポンスにしか絶対使わない型とかわかってるならアリかもしれない。
Avatar
Avatar
tarunon
そういうことする人は、別にletにしたとしてもinitしなおすと思うけど
omochimetaru 04-Jun-21 11:54 PM
そうなんだよね。init越しのセッター解放が可能なんだよね。
23:54
あ、だから、全部のフィールドを渡すタイプのinitが見えてるかどうか、で判断できるな・・・
23:55
制約されたフィールドをもつ特殊なケースでは、initでそれが渡せないようになってるか、init本文に検査がついてるはず。 (edited)
Avatar
tarunon 04-Jun-21 11:56 PM
例えば全部letでもsetName(String)->Selfな関数が生えてたらそれはvarを凄く遠回りに表現してるだけなのでやるべきじゃないし
23:56
同様にinitが解放されていて、ユーザによる変更結果をinit使って格納してたらそれも同じ。varを遠回りして書いてるだけ
23:58
違反mutableはコードレビューで var mUser = user の一行を👮‍♀️するだけだから、これもそこまで難しいとは思えないが…
23:58
うーーーん?
00:00
むしろ遠回りなコードは外れた違反コードを招いてコードレビューの難易度を上げるまである。素直にvarで置き直してたら変更が発生してると判断できた方が楽。
Avatar
niw 05-Jun-21 12:07 AM
先も言ったけど自分の責任じゃなくなる、がそうしたくなる大きな要因にも思える
00:07
varで使えるようになるのは自分の責任、 (edited)
00:08
letで書いておけばそれは防げる、みたいな。
Avatar
omochimetaru 05-Jun-21 12:09 AM
なるほど。
00:09
その間違ったコードが発生してもどう考えても型を作った人の責任じゃないと思うけど
00:11
そこで責任逃れを事前に備えておかなきゃいけない環境はつらそうだな。
Avatar
rintaro 05-Jun-21 12:12 AM
「init越しのセッター解放」ってたとえば
struct Point { let x: Int let y: Int init(x: Int, y: Int) { self.x = x; self.y = y } } extension Point { mutating func setX(_ x: Int) { self = .init(x: x, y: self.y) } }
という理解でいいですか?
Avatar
Avatar
rintaro
「init越しのセッター解放」ってたとえば
struct Point { let x: Int let y: Int init(x: Int, y: Int) { self.x = x; self.y = y } } extension Point { mutating func setX(_ x: Int) { self = .init(x: x, y: self.y) } }
という理解でいいですか?
omochimetaru 05-Jun-21 12:12 AM
まさにそれを想定しています。
👍 1
Avatar
tarunon 05-Jun-21 12:14 AM
「トップレベルがvarになっても安心じゃん」はinitで破壊されるわけだから、トップレベルをletで守るということを徹底するべき で、この前提が守られているなら途中のプロパティはvarでも何も問題が無いし、本当に変更したいときのコードはトップレベルをvarにするだけな簡素なものになる (edited)
00:14
前提のトップレベルがletであるべきを守れない環境はもう色々仕方ない
00:15
何も守れてないけどかりそめの安心に縋るしかないのかな
Avatar
Avatar
tarunon
「トップレベルがvarになっても安心じゃん」はinitで破壊されるわけだから、トップレベルをletで守るということを徹底するべき で、この前提が守られているなら途中のプロパティはvarでも何も問題が無いし、本当に変更したいときのコードはトップレベルをvarにするだけな簡素なものになる (edited)
omochimetaru 05-Jun-21 12:15 AM
前提として原則letで済ませることで、varを使うのは限られた状況なわけだから、それが目印になってレビューの起点になるよね。 (edited)
Avatar
tarunon 05-Jun-21 12:16 AM
そうなんだよ。それが型定義の側じゃなくて利用側にあることがレビューを楽にするんだよな
Avatar
omochimetaru 05-Jun-21 12:18 AM
うーんやっぱ逃れようとしてるシチュエーションの発生の想定があることにかなり違和感がある・・・ (edited)
Avatar
niw 05-Jun-21 12:19 AM
実際そんな状況があるとは思えなんだけど
00:19
たとえば過去の職場での経験とか、過剰なlet信仰とかそんな感じにも思えた
Avatar
omochimetaru 05-Jun-21 12:19 AM
過剰なlet進行は、Java系出身だとありえると思います。
Avatar
tarunon 05-Jun-21 12:20 AM
値型のコピー特性を理解したら信仰から解放されそう
Avatar
omochimetaru 05-Jun-21 12:20 AM
Swiftのstructだと理屈が違ってるんで破綻してるんですけど、あんまりわかってないままSwift書いてるとそうなると思う。
Avatar
niw 05-Jun-21 12:20 AM
実際class/structの混同というのも見られたけどそれはまあちょっとそもそもスタート地点に立っていないから実はまだlet信仰を改善できる感じがした
Avatar
omochimetaru 05-Jun-21 12:21 AM
Swiftでvar propertyを書き換えることとJavaのimmutable objectで新しいインスタンスを作ることが等価な事に気づいて欲しい。
Avatar
niw 05-Jun-21 12:21 AM
structをわかってなおかつlet信仰なのがでも実はswift好き組に結構いた感じがする
00:22
なんか直感的にはわからないのがなあ。
Avatar
omochimetaru 05-Jun-21 12:22 AM
その派は他人が作ったstructのpropertyがletで躓いた時にどうなるんだろう・・・
Avatar
niw 05-Jun-21 12:23 AM
あんまり考えてないかも。
00:23
「チームごとにルール作ればいいじゃん派」もいた
Avatar
omochimetaru 05-Jun-21 12:24 AM
varを間違って使う不毛な心配をするより、 letで不便が生じる心配をしたほうが良いはず。
Avatar
niw 05-Jun-21 12:25 AM
letをstructで使えるようにしたのが間違いだ派もいた
00:25
まあちょっとわからんでもない
Avatar
tarunon 05-Jun-21 12:25 AM
どういうことですか?propertyにletが置けるのがダメと
Avatar
niw 05-Jun-21 12:26 AM
それはvar推奨派でという意味
Avatar
tarunon 05-Jun-21 12:26 AM
理解。過激派ですねw
Avatar
niw 05-Jun-21 12:26 AM
なんか全体として、長くコードベースに関わってきた人はよりvar推奨で
00:27
年数の浅い方にlet推奨が多い感じだったかなあ
Avatar
omochimetaru 05-Jun-21 12:27 AM
まあ let なくても private(set) var で同じ事が起きますよ (edited)
Avatar
niw 05-Jun-21 12:27 AM
関係あるのかわからんけど、いろいろ触るとうわなんでこいつletやねんでつまづくから
Avatar
omochimetaru 05-Jun-21 12:28 AM
やっぱ経験が長いとletの不便を踏むのでは。
👆 2
Avatar
niw 05-Jun-21 12:28 AM
var推奨派が増えるのかもしれない
Avatar
tarunon 05-Jun-21 12:28 AM
あとは値型のコピー特性がSwift特有のものなので
Avatar
omochimetaru 05-Jun-21 12:28 AM
varの問題は大本letで解決するけどそっちはinit越しsetterとかいうハゲでしか回避できないですからね
Avatar
tarunon 05-Jun-21 12:28 AM
そこに対する理解を得るのに一定の時間が必要というのはあるかもですね
Avatar
niw 05-Jun-21 12:30 AM
immutable/mutableのNSObjetのペアをObjective-Cで書いたことあれば
00:30
varの利益がわかるはずという説明もあったけど共感できるんだけど
00:31
Objective-Cの経験年数が多い人がswift的には少ないという点共感がえられたか怪しい (edited)
Avatar
omochimetaru 05-Jun-21 12:31 AM
その経験がある時点でSwift歴も長くなってそう
Avatar
tarunon 05-Jun-21 12:32 AM
どんな言語でもstdlibのお作法に従うというのは鉄則なので、Array Dictionaryがそうしてるんだから俺達もそうするんだ
00:32
でも良い気はしますけどね
Avatar
niw 05-Jun-21 12:32 AM
swiftが初期にlet(というかimmutability)を宣伝しすぎたのはちょっと問題なのかも (edited)
Avatar
koher 05-Jun-21 01:13 AM
ずいぶん話が進んでた。「init越しのセッター解放」の最たる例が Booltoggle() で、 var 使ってる以上プロパティをどれだけ守っても可変だし、可変であっても共有されないから本質的にイミュータブルと同じなんだよなぁ。
01:14
参照型中心のオブジェクト指向言語から来ると、これに慣れるのにtarunonさんの言うようにある程度の時間がかかる。
Avatar
omochimetaru 05-Jun-21 01:14 AM
Boolはpropertyを持たないけどどういう意味ですか?
Avatar
koher 05-Jun-21 01:15 AM
一部のプロパティを let にして守った気になってるけど self 書き換えを extension で生やせるから守れてなくて、一部どころか全体すら書き換えられるから、イミュータブルに見える Bool ですらイミュータブルでないし、それで問題ないって意味。
Avatar
omochimetaru 05-Jun-21 01:16 AM
全体すら書き換えられる例ということか。
Avatar
koher 05-Jun-21 01:16 AM
toggle って参照型中心の世界の考え方に浸かってるとぶったまげると思うんよね。
01:17
BoolString がミュータブルってだけで泣いちゃいそう。
Avatar
masakihori 05-Jun-21 01:22 AM
extension Bool { var negate: Bool { !self } }
の方があり得る。けどこれは!を使えで蹴散らされる
Avatar
koher 05-Jun-21 01:22 AM
これが(他の言語での)普通の感覚ですよね。
Avatar
masakihori 05-Jun-21 01:23 AM
話を戻しちゃうけど 僕は個人開発者なので(?)初めは全部letにして必要になった時にvarにしてますね 自分が変えようと思た時にお気軽に変えられるので アクセス修飾 private/public の延長みたいな感覚 本当に必要になるまで public (var)にしない var絶対許さないマンもこの感覚かな?と思う
Avatar
omochimetaru 05-Jun-21 01:23 AM
toggled() は無いのか。
Avatar
masakihori 05-Jun-21 01:38 AM
共同開発の場合新しい型を作るより既存の型を変更する方が100万倍面倒くさいはずなので全部varにしておくほうがいいと思うけど、共同開発したことないので分からない
Avatar
niw 08-Jun-21 09:52 PM
struct A { let i: Int } struct B { let a: A? = nil } //let _: [Any] = [B()].compactMap { $0[keyPath: \B.a?.i] } // OK let _: [Any] = [B()].compactMap(\.a?.i)
21:53
segvする
Avatar
koher 10-Jun-21 03:14 AM
ふと思いついてやってみたんですけど、↓で JSON の encode / decode で元通り復元できないのって既知ですか? @swift-5.4.3
import Foundation struct Foo: Codable { var value: Int?? } let foo: Foo = .init(value: .some(.none)) print(foo) let data = try! JSONEncoder().encode(foo) print(String(data: data, encoding: .utf8)!) let decoded = try! JSONDecoder().decode(Foo.self, from: data) print(decoded)
Avatar
swift54 BOT 10-Jun-21 03:14 AM
Foo(value: Optional(nil)) {"value":null} Foo(value: nil)
Avatar
masakihori 10-Jun-21 03:26 AM
JSONでOptional<Optional<T>>が表現できないのにエンコードできちゃうのが間違えてると思う
Avatar
Avatar
koher
ふと思いついてやってみたんですけど、↓で JSON の encode / decode で元通り復元できないのって既知ですか? @swift-5.4.3
import Foundation struct Foo: Codable { var value: Int?? } let foo: Foo = .init(value: .some(.none)) print(foo) let data = try! JSONEncoder().encode(foo) print(String(data: data, encoding: .utf8)!) let decoded = try! JSONDecoder().decode(Foo.self, from: data) print(decoded)
rintaro 10-Jun-21 03:30 AM
Avatar
koher 10-Jun-21 03:31 AM
めっちゃ最近話されてたw
Avatar
tarunon 10-Jun-21 03:32 AM
キー無しとキー有りnullとで2重までは表現できるから
Avatar
koher 10-Jun-21 03:32 AM
enumCodable の話の文脈で話されてるっぽいけど、そもそも単体でこれまでに起こってた話なんですよね。
Avatar
tarunon 10-Jun-21 03:32 AM
正しく元に戻ってくれると嬉しいですね
Avatar
Avatar
masakihori
JSONでOptional<Optional<T>>が表現できないのにエンコードできちゃうのが間違えてると思う
koher 10-Jun-21 03:34 AM
tagged union を untagged union にマッピングしてるのでできなくて当たり前ですよね。ただ、 String? とかが Codable でないのはそれはそれで辛いですね。うーん。
Avatar
Avatar
tarunon
正しく元に戻ってくれると嬉しいですね
koher 10-Jun-21 03:35 AM
そこの区別は地獄の入口になりそう😅
Avatar
rintaro 10-Jun-21 03:35 AM
enumの自動Codableと同じように
"some": { "_0": { "some": { "_0": {...} } } } }
とかで表現すればいいわけだ。
Avatar
Avatar
rintaro
enumの自動Codableと同じように
"some": { "_0": { "some": { "_0": {...} } } } }
とかで表現すればいいわけだ。
koher 10-Jun-21 03:36 AM
そう、それを考えてて、ネストした Optional って今どうなってるんだ?と思ってやってみたら↑みたいになってたという・・・。でも、 98% くらいの用途である Foo? が自動 Codable 形式になるのは辛いですよね・・・。 (edited)
Avatar
rintaro 10-Jun-21 03:37 AM
T? だけ特別扱いは出来なくはなさそうですよね。
Avatar
tarunon 10-Jun-21 03:38 AM
そもそもjsonのoptionalはjsのoptional型相当なので、ちゃんとやるならCodable用のOptionalを作ってそこにマッピングする、ということになりそう
03:39
undefined(キー無し), null, someがある型
Avatar
Avatar
tarunon
そもそもjsonのoptionalはjsのoptional型相当なので、ちゃんとやるならCodable用のOptionalを作ってそこにマッピングする、ということになりそう
koher 10-Jun-21 03:44 AM
これもネストできるからダメそうな気が。
Avatar
tarunon 10-Jun-21 03:44 AM
CondConfにNot制約が必要ですねぇ
Avatar
koher 10-Jun-21 03:44 AM
ですね。
Avatar
tarunon 10-Jun-21 03:45 AM
それがあれば2重Optionalまで許可、と言う解決でシンプルになりそう
03:46
或いは、untagged unionを導入したら解決しますね
Avatar
Avatar
rintaro
T? だけ特別扱いは出来なくはなさそうですよね。
koher 10-Jun-21 03:46 AM
T?TOptional でないときみたいな条件書けますっけ?
Avatar
Avatar
tarunon
或いは、untagged unionを導入したら解決しますね
koher 10-Jun-21 03:47 AM
Swiftの世界観崩壊しそう😂
Avatar
tarunon 10-Jun-21 03:48 AM
ので、違う型システムに変換してる以上、100%の保証をするのは無理筋なのである程度の妥協があった方が良いとは思います (edited)
Avatar
Avatar
koher
T?TOptional でないときみたいな条件書けますっけ?
rintaro 10-Jun-21 03:49 AM
制約としては書けないと思いますけど、Optional.init(from:)/Optional.encode(to:) のstdlib実装なら可能だと思います。という意図でした。 (edited)
03:53
https://github.com/apple/swift/blob/038af80a880ce8581631f7c695f82dc20914f1d9/stdlib/public/core/Codable.swift#L5372-L5405 この辺の内部実装を WrappedOptional なら分岐させるっていう意味です。もちろん evolution proposal 必要ですけど。
Avatar
omochimetaru 10-Jun-21 04:08 AM
enumのcodableができたからoptionalもenumなので特別扱いは要らなくなりましたよね
Avatar
Kishikawa Katsumi 10-Jun-21 04:11 AM
なるほど。OptionalもEnumのAssociate value扱いでいいのか。
04:13
まあJSONに限るとJSONにない二重以上のオプショナルはそう扱っていい気もしますね。
Avatar
koher 13-Jun-21 08:53 AM
Actor 、↓のように書いたら
actor Counter { private(set) var count: Int = 0 func countUp(_ amount: Int) -> Int { count += amound return count } func countUp() -> Int { countUp(1) } }
(edited)
08:54
概念的には↓のように考えれば合ってる?
final class Counter { private let queue: DiqpatchQueue = ... // Serial Queue private var _count: Int = 0 var count: Int { get async { withCheckedContinuation { continuation in queue.async { continuation.resume(returning: _count) } } } } private func _countUp(_ amount: Int) -> Int { count += amound return count } func countUp(_ amount: Int) async -> Int { withCheckedContinuation { continuation in queue.async { continuation.returning(returning: _countUp(amount)) } } } private func _countUp() -> Int { _countUp(1) } func countUp() async -> Int { withCheckedContinuation { continuation in queue.async { continuation.resume(returning: _countUp()) } } } }
(edited)
08:55
あ、 increment の結果返さないと。 修正 done 。 (edited)
Avatar
omochimetaru 13-Jun-21 10:37 AM
あってるとおもいます
10:38
外から呼ぶときにqueue.async越しになる。
👌 1
Avatar
niw 13-Jun-21 10:19 PM
f (_ a: @escaping () async -> Void) { let s = DispatchSemaphore(value: 0) async { await a() s.signal() } s.wait() }
22:19
これやっちゃダメらしんですが、これでデッドロックとかするケースってあるんですかね。 (edited)
Avatar
koher 14-Jun-21 12:52 AM
a が元のスレッドに突入しようとしたらダメじゃないでしょうか?
00:53
f をメインスレッドで呼び出して aDispatchQueue.main.asyncasync/await 版を渡すとか。
Avatar
Avatar
niw
f (_ a: @escaping () async -> Void) { let s = DispatchSemaphore(value: 0) async { await a() s.signal() } s.wait() }
omochimetaru 14-Jun-21 03:36 AM
asnyc の中身が f を実行してる スレッドに投入される可能性がありますね。 async/awaitではブロッキングが起きないことを前提にスケジューラが構成されているらしいので、 他のTaskの処理がそのwaitしてるスレッドに投入されて複雑に噛み合った結果止まる可能性もあります。
Avatar
niw 14-Jun-21 04:07 AM
@MainActor func a() async { } func f() { let s = DispatchSemaphore(value: 0) async { await a() s.signal() } s.wait() } f()
04:07
これかー。
04:07
けっこう厳しいな、これ。libdispatch多用してる既存の世界でつかったら摩訶不思議なdeadlock起きそう。main threadならまだわかるけど。 (edited)
Avatar
omochimetaru 14-Jun-21 04:08 AM
そうですね。MainActorの場合は、必ずメインスレッドに再投入するので、さっきの話が100%発生します
Avatar
niw 14-Jun-21 04:08 AM
LIBDISPATCH_COOPERATIVE_POOL_STRICT で実行時に死ぬか確かめるしかないのか... わかるけど...
04:09
@MainActor 以外に thread 特定されるような要素ってなにがあるかな
04:10
簡単に試した限り async/await 系のAPIでcooperative threadつかってる範囲ではdeadlockできなかった
Avatar
omochimetaru 14-Jun-21 04:10 AM
ほかは無いはずですね。同じActorのpartial taskは別のスレッドで実行することもあるようなので。
04:11
Actorの内部にあるExecutorってやつがそのへんと関係してたはず。
04:12
ただ、Actor runtimeは(Montreyだと)スレッドプールが変動しないので、
04:12
そのようなwaitをしてるスレッドがコア数分発生したら
04:12
どのスレッドもpartial taskを実行しなくなって世界が止まりますね
Avatar
niw 14-Jun-21 04:12 AM
それ確認したいんだよなあ。Montereyいれるしかないのか...
Avatar
Avatar
niw
けっこう厳しいな、これ。libdispatch多用してる既存の世界でつかったら摩訶不思議なdeadlock起きそう。main threadならまだわかるけど。 (edited)
omochimetaru 14-Jun-21 04:14 AM
既存コードでは、上記パターンは asnyc ではなく DispatchQueue.asnyc で書いているはずで、
04:14
DispatchQueue.asyncはスレッドを作るので、signalまで到達しますね。
04:15
案外大丈夫なパターンが多いかもしれないです。 async/awaitスケジューラに負担はかかるので性能は低下するけど。
Avatar
niw 14-Jun-21 04:18 AM
部分的に async await を誰かが書いて semaphore を使ったAPIが離れた場所で残ってるで無事deadlockはありそう (edited)
04:19
semaphoreを遠距離で使うことは少ないはずだけど。
04:21
逆に言うと、実は全ての Task が完了するまで待つ、みたいなのって書けない?
Avatar
omochimetaru 14-Jun-21 04:25 AM
書けないと思います。
04:25
そもそも Task を作ったところで Task オブジェクトを引き回しておかないと
04:25
後で触りようもないので。
Avatar
niw 14-Jun-21 04:25 AM
トップレベルでタスクつくって終わるまでまっておわったら終了、が書けなかった。
04:25
十分な長さsleepするしかない
Avatar
omochimetaru 14-Jun-21 04:25 AM
それはかけないですね、Taskをまつのもawaitなので。
04:25
TaskはTaskの中でなければ待てない
Avatar
niw 14-Jun-21 04:26 AM
しかも十分な長さsleepしないとsegvする
04:28
並列 curl みたいな CLI を URLSession の async でつくるってできないのかも。
Avatar
omochimetaru 14-Jun-21 04:29 AM
一番根っこで
04:30
DispatchQueue.asnycで専用にスレッドを立ててsemaphoreを待って メインスレッドはその後 dispatchMain に入る (edited)
04:30
みたいな。あれ、でもCLIの場合asyncの世界の入り口ってどうやって書くんだったっけ。 (edited)
04:31
メインスレッドで最初からawait可能?
Avatar
niw 14-Jun-21 04:31 AM
それは無理
04:31
async {} aka Task.init {} か何かが必要 (edited)
Avatar
Avatar
omochimetaru
DispatchQueue.asnycで専用にスレッドを立ててsemaphoreを待って メインスレッドはその後 dispatchMain に入る (edited)
niw 14-Jun-21 04:32 AM
それはつまり semaphore.signal()/semaphore.wait()👆 みたいな安全ではないコードがどこかに必要になってしまう... (edited)
Avatar
omochimetaru 14-Jun-21 04:33 AM
あーじゃあ Task.init で起動するけど wait できないって状態か
Avatar
niw 14-Jun-21 04:33 AM
ですです
Avatar
omochimetaru 14-Jun-21 04:33 AM
最初に開いたTaskの末尾でsignal() しておいて
04:34
waitするのは専用のDispatchQueue.asyncの中
Avatar
niw 14-Jun-21 04:34 AM
さっきの f() がトップレベルで必要、ってことですよねえ。
Avatar
omochimetaru 14-Jun-21 04:34 AM
そのDispatchQueueに5.5 Concurrencyが絡んだら終わり
04:34
気をつける
Avatar
niw 14-Jun-21 04:34 AM
w
Avatar
omochimetaru 14-Jun-21 04:34 AM
まあCLIの一番上だけならいいんじゃないだろうか・・・一回ユーティリティ関数書けば大丈夫ですよ
04:35
なんか途中までそんな感じの関数があったけど途中で消えたんですよね。
Avatar
niw 14-Jun-21 04:35 AM
多分だけど、@MainActor 以外、cooperative thread pool の thread 以外は使われないから、さっきの f() が Task から呼ばれないことが保証されていれば絶対安全なんじゃないかなあ。
04:36
なるほど。
Avatar
omochimetaru 14-Jun-21 04:38 AM
さっきの f() が Task から呼ばれないことが保証されていれば
わかった、fの頭に Task.unsafeCurrentTask をチェックするassertionをいれとこう
Avatar
niw 14-Jun-21 04:38 AM
お!
Avatar
omochimetaru 14-Jun-21 04:38 AM
「Taskの中でない」ことは調べられるんですよ。
04:39
実行時検査なのは微妙だけど、ピタゴラスイッチデッドロックよりははるかに良い。
Avatar
niw 14-Jun-21 04:39 AM
Taskの中ではないを強制できないのかな?
04:39
notTask(_ t: @escaping () -> Void) みたいな (edited)
Avatar
Avatar
omochimetaru
みたいな。あれ、でもCLIの場合asyncの世界の入り口ってどうやって書くんだったっけ。 (edited)
koher 14-Jun-21 05:48 AM
↓これは?
@main struct MyProgram { static func main() async { ... } }
https://github.com/apple/swift-evolution/blob/main/proposals/0296-async-await.md#launching-async-tasks
Avatar
niw 14-Jun-21 05:49 AM
なんと
Avatar
Avatar
koher
↓これは?
@main struct MyProgram { static func main() async { ... } }
https://github.com/apple/swift-evolution/blob/main/proposals/0296-async-await.md#launching-async-tasks
omochimetaru 14-Jun-21 05:50 AM
それだ〜!
05:51
一回ユーティリティ関数書けば大丈夫ですよ
↑これがコンパイラ機能だった〜
Avatar
koher 14-Jun-21 05:53 AM
Additionally, top-level code is not considered an asynchronous context in this proposal, so the following program is ill-formed:
func f() async -> String { "hello, asynchronously" } print(await f()) // error: cannot call asynchronous function in top-level code
This, too, will be addressed in a subsequent proposal that properly accounts for top-level variables.
05:54
トップレベルについての議論の最新状態がどうなってるのかは知らない。
Avatar
niw 14-Jun-21 05:54 AM
@main じゃないと使えないのかなあ
Avatar
koher 14-Jun-21 05:55 AM
前はトップレベルで使えるようにする話があったはずなので、その後どうなったのか。
Avatar
niw 14-Jun-21 05:55 AM
--parse-as-library つけないと @main つかえない… (別の話ですが) (edited)
Avatar
niw 14-Jun-21 06:25 AM
現状 top-level は無理っぽい
06:25
@main 必須かなあ
Avatar
kateinoigakukun 14-Jun-21 06:26 AM
スクリプトモードでのトップレベルawaitは実装予定って最近もどっかで言ってたはず (edited)
Avatar
niw 14-Jun-21 06:27 AM
@MainActor @Sendable func _doMain(_ asyncFun: @escaping () async throws -> ()) async { do { try await asyncFun() } catch { _errorInMain(error) } } Task.detached { await _doMain(asyncFun) exit(0) } _asyncMainDrainQueue()
これが実装で、Task.detached して exit(0), main は CFRunLoopRun() ということらしい。
(edited)
Avatar
Avatar
kateinoigakukun
スクリプトモードでのトップレベルawaitは実装予定って最近もどっかで言ってたはず (edited)
niw 14-Jun-21 06:28 AM
なるほど
Avatar
niw 14-Jun-21 06:40 AM
なるほどな〜、これなら全てが Task の世界に。
Avatar
niw 14-Jun-21 07:33 AM
actor A { var c = 0 func inc() -> Int { c += 1 return c } func f() { async { print(inc()) } } } @main struct Main { static func main() async { let a = A() await a.f() print(await a.c) } }
07:34
これ f に async つけないと終了しない
Avatar
omochimetaru 14-Jun-21 07:36 AM
それはなんか変ですね。
Avatar
niw 14-Jun-21 07:36 AM
Taskが漏れてる?
Avatar
kateinoigakukun 14-Jun-21 09:19 AM
@swift-nightly
actor A { var c = 0 func inc() -> Int { c += 1 return c } func f() { async { print(inc()) } } } _runAsyncMain { let a = A() await a.f() print(await a.c) }
Avatar
swiftNightly BOT 14-Jun-21 09:19 AM
1 1
stderr:
<stdin>:10:9: warning: 'async(priority:operation:)' is deprecated: `async` was replaced by `Task.init` and will be removed shortly. async { ^
Avatar
Avatar
niw
これ f に async つけないと終了しない
kateinoigakukun 14-Jun-21 09:20 AM
ここで付けないといけなかったasyncって func f() async ですか?それともbodyの async { .. } ですか?
09:22
手元で動かしたんですが、 main側のprintが実行されたり、されなかったりしててかなり怪しい… (edited)
09:23
bodyの async { .. } を外すと(今の所)必ず実行されてるように見える (edited)
Avatar
Avatar
kateinoigakukun
ここで付けないといけなかったasyncって func f() async ですか?それともbodyの async { .. } ですか?
niw 14-Jun-21 02:50 PM
f() async ですね。
Avatar
Avatar
kateinoigakukun
手元で動かしたんですが、 main側のprintが実行されたり、されなかったりしててかなり怪しい… (edited)
niw 14-Jun-21 02:52 PM
main で、actor の c にアクセスしてブロックしないと、taskの待ち合わせを誰もしないので print されないで終了するパターンは納得がいくんだけど (Taskを待ち合わせる方法がないという点で)、f()がasyncかそうでないかで、デッドロック?するかしないかが変わるにはとても怪しいんですよね。 (edited)
14:53
Actor の実装の問題かなあ。どっちもコンパイルはできてしまう。あるいは、手元は big sur だから、runtimeの問題かもしれない。 (edited)
Avatar
kateinoigakukun 14-Jun-21 03:02 PM
f() async してもデッドロックしてるっぽいんですよね
15:05
いや、viewDidLoadでasyncに包んでるのがマズイっぽいな
15:09
トップを_runAsyncMainして、 func f() async にするとデッドロックしなくなった。これでniwさんの環境を再現できた気がする
15:14
fにasyncを付けるとmainの await a.f() 以下と fの async { .. } ブロックの中が同じスレッドで実行されるようになるっぽい…
🤔 1
15:16
@swift-nightly
import Foundation actor A { var c = 0 func inc() -> Int { c += 1 return c } func f() async { async { print("begin f") print(Thread.current) print(inc()) print("end f") } } } _runAsyncMain { print(Thread.current) let a = A() await a.f() print("begin main") print(Thread.current) print(await a.c) print("end main") }
Avatar
swiftNightly BOT 14-Jun-21 03:16 PM
<Thread: 0x00007fd110000c60> begin main <Thread: 0x00007fd114002dd0> 0 end main begin f <Thread: 0x00007fd114002dd0> 1 end f
stderr:
<stdin>:13:9: warning: 'async(priority:operation:)' is deprecated: `async` was replaced by `Task.init` and will be removed shortly. async { ^
Avatar
kateinoigakukun 14-Jun-21 03:16 PM
@swift-nightly
import Foundation actor A { var c = 0 func inc() -> Int { c += 1 return c } func f() { async { print("begin f") print(Thread.current) print(inc()) print("end f") } } } _runAsyncMain { print(Thread.current) let a = A() await a.f() print("begin main") print(Thread.current) print(await a.c) print("end main") }
Avatar
swiftNightly BOT 14-Jun-21 03:16 PM
<Thread: 0x00007f3114000c60> begin f <Thread: 0x00007f3118003360> 1 end f begin main <Thread: 0x00007f3114000c60> 1 end main
stderr:
<stdin>:13:9: warning: 'async(priority:operation:)' is deprecated: `async` was replaced by `Task.init` and will be removed shortly. async { ^
Avatar
niw 14-Jun-21 04:21 PM
なる... ほど...?
16:23
func msg(f: String = #function, _ s: Any) { print("\(Thread.current): \(f): \(s)") } actor A { var c = 0 func inc() -> Int { c += 1 return c } func f() { msg("3") async { msg("4") print(inc()) } } } @main struct Main { static func main() async { msg("1") let a = A() await a.f() msg("2") print(await a.c) } }
(edited)
16:23
これで
16:24
<NSThread: 0x7fa109c0bfd0>{number = 1, name = main}: main(): 1 <NSThread: 0x7fa109d05540>{number = 2, name = (null)}: f(): 3 <NSThread: 0x7fa109d05540>{number = 2, name = (null)}: f(): 4 1 <NSThread: 0x7fa109c0bfd0>{number = 1, name = main}: main(): 2 ^Cmake: *** [run] Interrupt: 2
deadlockした場合
16:24
<NSThread: 0x7f9250d0bfb0>{number = 1, name = main}: main(): 1 <NSThread: 0x7f9250e05b80>{number = 2, name = (null)}: f(): 3 <NSThread: 0x7f9250e05b80>{number = 2, name = (null)}: f(): 4 1 <NSThread: 0x7f9250d0bfb0>{number = 1, name = main}: main(): 2 1
deadlockしなかった場合
16:24
🤔
16:27
なんか、deadlockしない場合もあることがわかったけど、タイミング次第なのか... (edited)
Avatar
kateinoigakukun 14-Jun-21 04:28 PM
こういうのを静的にガードするためのactorだったはずなのに… (edited)
Avatar
niw 14-Jun-21 04:28 PM
f()にasyncつけるかつけないかで挙動が変わるのもあやしい
16:29
actorむずい
😢 1
Avatar
kateinoigakukun 14-Jun-21 04:29 PM
actorがexecutorにタスクを投入するところのコード生成実装を追ったら分かりそう
Avatar
niw 14-Jun-21 04:30 PM
inc()でthreadをprintするようにしたらdealockしないケースが発生しなくなった...
16:30
IO関係か?
Avatar
kateinoigakukun 14-Jun-21 04:32 PM
🤔
Avatar
niw 14-Jun-21 08:03 PM
actor A { func g() { } func f() { async { g() } } } @main struct Main { static func main() async { let a = A() await a.f() await a.f() // ここでdeadlock.. したりしなかった } }
(edited)
20:04
これでだめだ。 (edited)
Avatar
shiz 14-Jun-21 10:39 PM
async(priority: .background) { などpriority変えても起きますか?
Avatar
niw 14-Jun-21 10:41 PM
backgroundにするとdeadlockしないですね
22:41
あれ、でもg()が呼ばれないケースが...
22:41
あー。それはいいのか。
22:41
いいのか...?
🤔 1
Avatar
niw 14-Jun-21 10:50 PM
actorがどうやってsyncしてるのかと、asyncしたときのcontextの問題か...
Avatar
shiz 14-Jun-21 10:58 PM
はい、priorityに応じて処理をどういう順番で実行するのかを決める所で何か起きているのかなあとふと思いました🤔 (edited)
Avatar
shiz 16-Jun-21 10:55 AM
全然中身追えてませんがやはりpriority何か問題あるのかもしれませんね…🤔 https://github.com/apple/swift/pull/37939
Avatar
niw 16-Jun-21 02:01 PM
おお。
Avatar
koher 24-Jun-21 02:05 AM
AsyncSequencePublisher の代わりをさせるとして、 combineLatestmerge 相当のことを簡潔に実現するのは難しいでしょうか? AsyncSequencecombineLatestmerge が生えれば解決?
Avatar
tarunon 24-Jun-21 02:26 AM
今だと自前のオペレーターを作れば良いと思いますが、制約が結構あるので大変そう。 AsyncStream が出てきたら割と何でも出来るようになると思います。
Avatar
omochimetaru 24-Jun-21 02:36 AM
combineLatest難しいかな?
Avatar
koher 24-Jun-21 02:36 AM
たとえば自前で combineLatest 作るとしたら↓みたいに並行でループ回してとかでしょうか?
var values: (S1.Element?, S2.Element?) = (nil, nil) { didSet { switch values { case (let e1?, let e2?): // (e1, e2) をイテレータに流す case (.nil, nil): // nil をイテレータに流す default: break } } } async { for await e in s1 { values = (e, values.1) } } async { for await e in s2 { values = (values.0, e) } }
Avatar
tarunon 24-Jun-21 02:37 AM
難しいじゃなくて大変だという話ね
02:38
AsyncSequenceの実装を一から作らなきゃいけないから面倒
Avatar
omochimetaru 24-Jun-21 02:38 AM
AsyncStream { (cont) in var a: A! var b: B! async { for await x in a_s { a = x cont.yield(a, b) } } async { for await x in b_s { b = x cont.yield(a, b) } } }
(edited)
02:38
雰囲気はこんなかんじだよね
02:39
asyncの返り値のTaskをまとめて onTermination で cancel するとか、なんかあといろいろあるけど。
02:39
少なくとも、RxSwiftで自分でカスタムオペレータを書くよりは、
Avatar
koher 24-Jun-21 02:40 AM
やっぱそういう形になるよね。都度実装は面倒そうだから AsyncSequencecombineLatest はほしいな。
Avatar
omochimetaru 24-Jun-21 02:40 AM
AsnycSequence上のカスタムオペレータのコードのほうが簡単に書けそうと思ってる
02:40
まあ基本的なものは提供されてほしいですね。ArrayとかOptionalにflatMapがあるのと同じで。
Avatar
koher 24-Jun-21 02:42 AM
combineLatest とかはサードパーティ提供になりそうな気がするなぁ。
Avatar
tarunon 24-Jun-21 02:42 AM
flatMapはあるんだよね
Avatar
omochimetaru 24-Jun-21 02:42 AM
Sequenceにあるものはとりあえずあるんだっけ
02:42
combineLatestはSequenceには無いけどAsyncSequenceだとほしいね。
Avatar
koher 24-Jun-21 02:43 AM
基本 Sequence と同じのしかないですよねー。
Avatar
omochimetaru 24-Jun-21 02:43 AM
ただ、実装がしやすいってのは重要だと思ってて、ライブラリも出てきやすいと思う。
Avatar
koher 24-Jun-21 02:43 AM
サードパーティライブラリはたくさん出てくると思う。
Avatar
omochimetaru 24-Jun-21 02:43 AM
Rxとかだと、思いついても実装が難しいから、もりあがりにくい
Avatar
kateinoigakukun 24-Jun-21 02:44 AM
asyncなflatMap書きやすそう。Combineで起きたeraseToAnyPublisher問題も解決するし。
Avatar
Avatar
koher
サードパーティライブラリはたくさん出てくると思う。
omochimetaru 24-Jun-21 02:46 AM
しばらく様子見てから標準に追加するものを議論する流れになる気がします
Avatar
koher 24-Jun-21 02:47 AM
有用なものが標準に追加されるといいなぁ。結構標準ライブラリは保守的だと思うから。 (edited)
Avatar
omochimetaru 24-Jun-21 02:50 AM
swift-collectionsみたいに外部化されるかもしれないですね
02:50
swift-streamsみたいな。
Avatar
koher 24-Jun-21 02:52 AM
Apple製の準標準なら外部でもいいね。メンテの継続が期待できるから。 (edited)
Avatar
omochimetaru 24-Jun-21 02:57 AM
確かにそこが結構違いますね。一瞬流行ったライブラリでもメンテが止まるのがワリとある
Avatar
Avatar
kateinoigakukun
asyncなflatMap書きやすそう。Combineで起きたeraseToAnyPublisher問題も解決するし。
tarunon 24-Jun-21 04:01 AM
これは怪しい予感がする…
04:02
型は雪だるまなんだよな (edited)
Avatar
kateinoigakukun 24-Jun-21 04:02 AM
だめじゃん…
04:03
そっかストリーム自体は言語機能として表現できないからダメか
Avatar
tarunon 24-Jun-21 04:03 AM
いうてSequence.flatMapがArrayなのはズルしてるだけですからね
04:03
事実上のTypeErasure (edited)
Avatar
kateinoigakukun 24-Jun-21 04:05 AM
AnyAsyncSequeceがひつよう
Avatar
koher 02-Jul-21 10:16 AM
↓みたいなこと書こうとしたらコンパイルエラーになった。 guard let でシャドーイングすると、 { } の中では(バインド先の変数にアクセスできないのは当たり前として)元の変数にもアクセスできなくなる。コードリーディング時の勘違いを減らすにはこれでいいのかもしれないけど・・・。
guard let response = response as? HTTPURLResponse else { assertionFailure("Never reaches here.") print(type(of: response)) return }
(edited)
Avatar
Kishikawa Katsumi 02-Jul-21 10:17 AM
guard letのこれは私もちょくちょく不便だなと思っています。
😢 1
Avatar
omochimetaru 02-Jul-21 11:31 AM
あーそうか。元は見えて良いですねこれ。
Avatar
koher 02-Jul-21 01:23 PM
理論上はそうなんだけど、↑のコードをぱっと見で print(type(of: response))response がシャドーイング前のものって読み取りづらい気もするから、まあ妥当な制約かもなぁと。これまで遭遇したことなかったからこんなケースあったのかと思って。↑のケースでは結局 guard let httpResponse = response as? ... にした。
Avatar
omochimetaru 07-Jul-21 03:06 AM
I am sorry if I missed this (I haven't had a chance to read through all the posts above, so maybe this is out of scope or unsupported) but I was wondering if it would be possible to assign a shared value to all instances declared in a given type? For example, I might have a @Preference property wrapper and I want to inject an instance of some ty...
03:06
このスレちまちま読み進めてやっと追いついた
03:08
static function parameter はなんか不思議な機能だけど便利そうな気もする
Avatar
tarunon 07-Jul-21 03:11 AM
言語機能としてサポートされると、Reactだとreducerやstoreの宣言がstaticに出来ていてhookを使うのが楽、みたいなのが、SwiftUIでも再現できるようになるかもしれないみたいなことをぼんやり考えていた
Avatar
omochimetaru 07-Jul-21 03:15 AM
Reactの件がどういう話かわからないけど、これは指定はしないといけないから、ユーザー側の楽さは変わらない話だと思うよ
03:15
実行時の値が静的に定義されてポインタ渡しになるという話
Avatar
tarunon 07-Jul-21 03:21 AM
議論が2,3段あるので説明が面倒いのだけどwebアプリだとブラウザのbackForardListがあるお陰でstatic宣言されたものも事実上インスタンス化されている、みたいなところがあってiOSだとそれは出来ないが、shared storageが解決しそうだねって話。 static function parameterは言及先ではなかった
Avatar
omochimetaru 07-Jul-21 03:29 AM
インスタンス間で同じものを参照してる構造にマッチするということかな
Avatar
tarunon 07-Jul-21 03:39 AM
そうそう
03:42
枝葉のコンポーネントはhookで親のコンポーネントが持つリソースにアクセスしたいが、親が異なる場合は異なるリソースになる。 ブラウザだとここにbackForardListが挟まるのでstatic宣言でも成り立つ(まあ色々あるけど省略する)が、iOSだとNavigationStackに詰まれてるからそういう飛び道具にstatic変数は使いにくかった
Avatar
lovee 02-Aug-21 06:48 AM
Swiftのdefer、いつから変数宣言前から使えるようになったっけ…?
do { defer { print(a) } // ←まだaが宣言されてないよ…? let a = 0 }
Avatar
omochimetaru 02-Aug-21 08:02 AM
バグだと思う 名前解決がそうなる状況他にないし
Avatar
Avatar
lovee
Swiftのdefer、いつから変数宣言前から使えるようになったっけ…?
do { defer { print(a) } // ←まだaが宣言されてないよ…? let a = 0 }
niw 02-Aug-21 03:46 PM
便利。。
Avatar
Avatar
lovee
Swiftのdefer、いつから変数宣言前から使えるようになったっけ…?
do { defer { print(a) } // ←まだaが宣言されてないよ…? let a = 0 }
rintaro 02-Aug-21 04:29 PM
Swift 5.5 で殺されてますね https://github.com/apple/swift/pull/36441 @swift-nightly
do { defer { print(a) } // ←まだaが宣言されてないよ…? let a = 0 }
... お、swiftbot-sandbox でさんざん実験済みだったのか笑
(edited)
While &#39;defer&#39; is implemented as a local function, it doesn&#39;t behave as one. In particular, since SILGen runs it after destroying all local bindings that appear after the &am...
Avatar
swiftNightly BOT 02-Aug-21 04:29 PM
exit status: 1 with stderr:
<stdin>:2:19: error: use of local variable 'a' before its declaration defer { print(a) } // ←まだaが宣言されてないよ…? <stdin>:3:9: note: 'a' declared here let a = 0 ^
Avatar
lovee 03-Aug-21 07:39 AM
Swift Forumsに上げたらChris Lattner氏にコメントもらった 🤪 https://forums.swift.org/t/defer-can-take-variables-declared-after-itself-bug-or-feature/50821/8 (edited)
Yeah, I agree -- this seems like a compiler bug to me.
Avatar
omochimetaru 03-Aug-21 07:40 AM
おお、SE登録された。あれ、でももうnightlyでバグとして検出されるようになっているのに? (edited)
Avatar
Ensan 04-Aug-21 03:46 PM
Currently, we only support opaque result types as top level level types, e.g. some P is allowed but not (some P)?. This branch adds support for opaque result types in structural type positions.
15:46
(some P)? みたいなのができるようになるっぽい?
🙌 1
Avatar
omochimetaru 04-Aug-21 04:17 PM
見かけないアイコンだ
Avatar
Ensan 04-Aug-21 04:18 PM
少し前にリバースジェネリクスのPR出してた人ですね
Avatar
omochimetaru 04-Aug-21 04:20 PM
ほおー
16:20
func twoOpaqueTypes() -> (some P, some P) { return (1, 2) } // expected-error{{only one 'opaque' type is supported}}
16:20
2つはだめらしい?
16:20
それは続きなのかな。
Avatar
Ensan 04-Aug-21 04:22 PM
ジェネリック型全般で使えるのはかなり楽になりそう
16:24
// ERROR: function declares an opaque return type, but has no return statements in its body from which to infer an underlying type // func asHOFRetArg() -> (some P) -> () { return { (x: String) -> () in } } //
これなんでinferできないんだろう
(edited)
Avatar
omochimetaru 04-Aug-21 05:30 PM
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
17:30
↑裏技集が出た
Avatar
koher 05-Aug-21 01:40 AM
知らないのめっちゃある・・・。
Avatar
niw 05-Aug-21 02:27 AM
裏技集w
Avatar
Kishikawa Katsumi 05-Aug-21 04:07 AM
@_optimize([none|size|speed]) これおもしろい。 関数ごとに最適化モード変えられるんだ。
04:08
リリースモード(最適化あり)だと不具合があるパターンのときに、全体をデバッグモードでビルドしなくても回避できたりする?のかな?
Avatar
kateinoigakukun 05-Aug-21 04:10 AM
その目的でたまに使いますね
Avatar
Kishikawa Katsumi 05-Aug-21 04:12 AM
使えるんだ!いいことを聞いた。
Avatar
omochimetaru 05-Aug-21 04:12 AM
opt noneそれいいですよね。 コード生成を観察する時にも便利。
Avatar
Kishikawa Katsumi 05-Aug-21 04:13 AM
へえ〜
04:14
というか眺めてるとほとんどの最適化というかコンパイラの挙動は関数単位で制御できてなんか困った場合は関数単位でいろいろやったらいいということか。
Avatar
Iceman 05-Aug-21 04:14 AM
え、これ逆に普段デバッグモードで作業しつつ特定の高負荷な関数だけ最適化するとかもできるんですか?
Avatar
Kishikawa Katsumi 05-Aug-21 04:14 AM
できそう。
Avatar
kateinoigakukun 05-Aug-21 04:15 AM
そっちはできるのかな
Avatar
omochimetaru 05-Aug-21 04:15 AM
下げ方向にしか効かないのか、それとも、関数指定が絶対優先するのか (edited)
04:16
たしかにデバッグで作業したいけど特定箇所の性能が落ちて全体がどうしようもないみたいな事あるな
Avatar
Kishikawa Katsumi 05-Aug-21 04:16 AM
@_optimize(none) func fib1() {...} @_optimize(speed) func fib2() {...}
こういうのを用意したら確かめられるかな?
Avatar
kateinoigakukun 05-Aug-21 04:16 AM
多分sizeとspeedは最適化パス内での挙動を操作するやつで、最適化パス列自体のプランニングは変わらない気がする (edited)
Avatar
Kishikawa Katsumi 05-Aug-21 04:16 AM
なるほど。
Avatar
omochimetaru 05-Aug-21 04:16 AM
ああそっか、例のパイプライン構築は別であるからか
Avatar
Iceman 05-Aug-21 04:17 AM
逆はだめか〜
Avatar
Kishikawa Katsumi 06-Aug-21 12:45 AM
@_private(sourceFile: "FileName.swift")
Fully bypasses access control, allowing access to private declarations in the imported module. The imported module needs to be compiled with -Xfrontend -enable-private-imports for this to work.
これも便利そうだ
Avatar
kateinoigakukun 06-Aug-21 12:46 AM
SwiftUIのプレビューに使われてるやつですね
Avatar
Kishikawa Katsumi 06-Aug-21 12:48 AM
おお、そういうことか!
Avatar
noppe 06-Aug-21 06:14 AM
@_spi import でも似たようなことができますね(こっちはパッケージ単位だけど)
Avatar
Kishikawa Katsumi 06-Aug-21 12:22 PM
Marks a declaration as SPI (System Programming Interface), instead of API. Modules exposing SPI and using library evolution generate an additional .private.swiftinterface file (with -emit-private-module-interface-path) in addition to the usual .swiftinterface file. This private interface exposes both API and SPI. Clients can access SPI by marking the import as @_spi(spiName) import Module. This design makes it easy to find out which clients are using certain SPIs by doing a textual search.
なるほどねえ。 SPI(System Programming Interface)というのはなんなのですか?
Avatar
omochimetaru 06-Aug-21 01:41 PM
それよく知らないままだ
03:45
マージされてたけど、さっきリバートされてた
Avatar
omochimetaru 27-Aug-21 03:45 AM
え〜。
03:45
これあればうれしい場面に遭遇しているのではやくほしい。
Avatar
niw 27-Aug-21 05:10 AM
revert...
Avatar
kateinoigakukun 27-Aug-21 05:11 AM
まー壊したテスト直せば再上陸できそう
Avatar
koher 29-Aug-21 10:34 AM
URLSession の新しい data(from:) メソッドを Taskcancel メソッドでキャンセルしたら、 CancellationError じゃなくて code == NSURLErrorCancelledNSErrorthrow される😂
10:34
Version 13.0 beta 5 (13A5212g)
Avatar
omochimetaru 29-Aug-21 10:34 AM
あ~ それはそうなりそう・・・
10:35
NSErrorから URLError
10:35
as でキャストできますよ
10:35
そのあと e.code == .cancelled かな
Avatar
koher 29-Aug-21 10:35 AM
これは data(from:) メソッドの実装で code をチェックして CancellationError を投げるべきでは?
10:36
というか、 Task がキャンセルされているかをチェックして URLSessionDataTask をキャンセルしてるコードがあるはずで、そこで管理すべき?
Avatar
kateinoigakukun 29-Aug-21 10:36 AM
checkCancellation が投げるデフォルトのエラーとして CancellationError は定義されてるけど、Concurrencyのキャンセル機構としてそこは実装依存か
10:38
例えば、キャンセルまでに得られた途中のデータを伝えるためにエラーオブジェクトにデータを入れる、みたいなケースは結構あると思うので CancellationError に寄せるのは難しいと思います (edited)
Avatar
koher 29-Aug-21 10:41 AM
CancellationErrorvar source: Error? を持つようにすれば解決できそうな?
Avatar
kateinoigakukun 29-Aug-21 10:42 AM
そうですねー。1つの解決策だと思います
10:43
もしくはプロトコルになってたら良かったんですかね。
Avatar
koher 29-Aug-21 10:44 AM
うーん、 CancellationErrorisCancelled == true のときに Task.checkCancellation が投げるエラーというだけで、キャンセルされたときに throw されるエラーは CancellationError とは限らないという仕様なのかな? catch let error as CancellationError でキャンセルをチェックするのではなく、 catch 節の中で Task.isCancelled でチェックするのが正しい? (edited)
10:49
URLSessiondata(from:) がどこで実装されてるのか見つからない・・・。
10:56
Conventionally, most functions that check for cancellation report it by throwing CancellationError()
だから必ずしも CancellationErrorthrow しなくても良い?でも
Operations running synchronously as part of the task can check this flag and are conventionally expected to throw a CancellationError
とあるので、 CancellationErrorthrow することが期待されている? URLSession.data(from:)cancel 時に CancellationErrorthrow しないのはお行儀が悪い? https://github.com/apple/swift-evolution/blob/main/proposals/0304-structured-concurrency.md#cancellation
(edited)
11:00
For tasks that would prefer to immediately exit with a thrown error on cancellation, the task API provides a common error type, CancellationError, to communicate that the task was cancelled.
この communicate の温度感もわからないな。キャンセルされたことを CancellationError として検出できるように、くらいの意味まで持つならキャンセル時に独自のエラーを throw するのではなく CancellationErrorthrow すべきとなりそうだけど。
11:02
いずれにせよ、キャンセル時にどんなエラーが投げられるかは実装依存だから、 API 利用側でキャンセルされたかを区別する必要がある場合、
do { try await foo() } catch let error as CancellationError { // キャンセル時の処理 } catch { // エラーハンドリング }
とするよりも
do { try await foo() } catch { if Task.isCancelled { // キャンセル時の処理 } else { // エラーハンドリング } }
がベストプラクティス?
(edited)
Avatar
kateinoigakukun 29-Aug-21 11:03 AM
キャンセルされたかどうかはthrowされたエラーで決められるのではなく、 cancel メソッドを呼んだレシーバのTaskに対してキャンセルフラグが立つ実装になっています。
Avatar
Avatar
kateinoigakukun
キャンセルされたかどうかはthrowされたエラーで決められるのではなく、 cancel メソッドを呼んだレシーバのTaskに対してキャンセルフラグが立つ実装になっています。
koher 29-Aug-21 11:04 AM
cancel メソッドを呼んだレシーバのTaskに対してキャンセルフラグが立つ実装
それを受けて、非同期 API 実装側は Task.checkCancellation() を呼ぶか、 Task.isCancelled をチェックして適切な処理を行った後に CancellationErrorthrow するというルールなのかと思っていました。
Avatar
kateinoigakukun 29-Aug-21 11:08 AM
なるほど。
11:09
そういう意味だと、 CancellationErrorはlightweightなキャンセル通知を意図したもので、キャンセル時にはCEを使うのがルール、ということはないと思います。 (edited)
11:10
It is intentional that no information is passed to the task about why it was cancelled. A task may be cancelled for many reasons, and additional reasons may accrue / after the initial cancellation (for example, if the task fails to immediately exit, it may pass a deadline). The goal of cancellation is to allow tasks to be cancelled in a lightweight way, not to be a secondary method of inter-task communication.
(edited)
Avatar
koher 29-Aug-21 11:13 AM
なるほど。じゃあやっぱり API 利用側がキャンセルをハンドリングする必要がある場合は catch 節で Task.isCancelled でチェックするのが良さそうですね。 (edited)
11:15
たとえば、 func download(...) async throws -> Data を呼び出して、自分がキャンセルボタンを押した場合と何かしらエラーが発生した場合のどちらもエラーが throw されるけど、前者では何もしないけど後者ではアラートを出したいみたいなケースを想定しています。 (edited)
Avatar
rinsuki 29-Aug-21 11:18 AM
となると
try { await download() } catch { if Task.isCancelled { throw error // or return } switch error { case let error as HogeError: // ... } }
みたいな感じになるんですかね?
(edited)
Avatar
Avatar
rinsuki
となると
try { await download() } catch { if Task.isCancelled { throw error // or return } switch error { case let error as HogeError: // ... } }
みたいな感じになるんですかね?
(edited)
koher 29-Aug-21 11:19 AM
そうなのかなぁとイメージしてます。
Avatar
omochimetaru 29-Aug-21 11:19 AM
Task.isCancelled だと
Avatar
kateinoigakukun 29-Aug-21 11:19 AM
その場合は、downloadするTaskはUnstructuredな Task インスタンスとしてどこかに保持されていると思うので、 そのTaskに対して task.isCancelled するのが良いと思います。
Avatar
omochimetaru 29-Aug-21 11:19 AM
Task APIでキャンセルした場合しかtrueにならないですよね
11:19
URLSessionのcancelメソッドを直接呼んだ場合とかが逆に漏れる
Avatar
Avatar
omochimetaru
Task APIでキャンセルした場合しかtrueにならないですよね
koher 29-Aug-21 11:20 AM
API 利用側はどのような手段でキャンセルしたかは知っているからいいんじゃないかな?キャンセルするのも、キャンセルをハンドリングする(アプリの挙動を変える)のも利用側なので。 (edited)
Avatar
omochimetaru 29-Aug-21 11:20 AM
なるほど
Avatar
Avatar
kateinoigakukun
その場合は、downloadするTaskはUnstructuredな Task インスタンスとしてどこかに保持されていると思うので、 そのTaskに対して task.isCancelled するのが良いと思います。
koher 29-Aug-21 11:22 AM
catch でエラーが飛んできたところで分岐しないといけなくないですか?それとも Task { } の中で catch せずに task.result で結果を受け取った方が良い?
Avatar
kateinoigakukun 29-Aug-21 11:27 AM
var downloadTask: Task<Data, Error>? func didTapDownload() { let task = Task { try await download(...) } self.downloadTask = task do { let result = try await task.value } catch { if task.isCancelled { ... } } } func didTapCancell() { self.downloadTask?.cancel() }
こういうのを想像してました。
(edited)
👍 1
Avatar
Avatar
kateinoigakukun
var downloadTask: Task<Data, Error>? func didTapDownload() { let task = Task { try await download(...) } self.downloadTask = task do { let result = try await task.value } catch { if task.isCancelled { ... } } } func didTapCancell() { self.downloadTask?.cancel() }
こういうのを想像してました。
(edited)
koher 29-Aug-21 11:37 AM
これdidTapDownloadがasyncじゃないから、やっぱりTask { }のクロージャ式の中でハンドリングした方が良さそうな?
Avatar
kateinoigakukun 29-Aug-21 11:40 AM
あー、そういうことでしたか。
11:40
たしかに didTapXX はasyncにできないからStructuredにしちゃいけないですね
11:42
そうするとTask { } クロージャの中でcatchするのか…
Avatar
koher 29-Aug-21 11:43 AM
そうなるとやっぱりTask.isCancelledでチェックかなぁ。
Avatar
kateinoigakukun 29-Aug-21 11:46 AM
そうですねえ。 URLSessionがcancelをハンドリングして大域脱出してるところを、同じタスク内で途中で掴むのは若干気持ち悪いんですが、これは感覚の問題なのかな。
Avatar
Avatar
kateinoigakukun
そうですねえ。 URLSessionがcancelをハンドリングして大域脱出してるところを、同じタスク内で途中で掴むのは若干気持ち悪いんですが、これは感覚の問題なのかな。
koher 29-Aug-21 12:51 PM
うーん、そう言われると確かに若干気持ち悪い気も。ただ、 download の戻り値をわざわざ Task の外側でハンドリングするのも若干気持ち悪い気もするし、 task.valueasync の中に入れるためにもう一つ Task 作るとかはもっと気持ち悪いので仕方なさそうですね。 (edited)
Avatar
kateinoigakukun 29-Aug-21 01:04 PM
そうなんですよ。仕方ない 😢
Avatar
shiz 29-Aug-21 09:41 PM
昨日、ちょうど同じようなところを見ていて、メソッド内でCancellationErrorをスローしたい場合は https://github.com/apple/swift-evolution/blob/main/proposals/0304-structured-concurrency.md#cancellation-handlers のソースコード例に書いてあるように(urlSessionTask captureしないとコンパイルできない)
func download(url: URL) async throws -> Data? { var urlSessionTask: URLSessionTask? return try withTaskCancellationHandler { return try await withUnsafeThrowingContinuation { continuation in urlSessionTask = URLSession.shared.dataTask(with: url) { data, _, error in if let error = error {     ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ // Ideally translate NSURLErrorCancelled to CancellationError here continuation.resume(throwing: error) } else { continuation.resume(returning: data) } } urlSessionTask?.resume() } } onCancel: { urlSessionTask?.cancel() // runs immediately when cancelled } }
withTaskCancellationHandler使って手動でチェックするのがいいんですかね?(結局呼び出し側でError Typeチェックしなければいけないので、あまり意味ない気もしますが...)🤔
(edited)
Avatar
koher 30-Aug-21 01:15 AM
おおお、ここ完全に見逃してました。
01:18
あー、これは非同期 API 利用側がキャンセルをハンドリングするためのものではなくて、実装側がキャンセルをハンドリングするためのものか。
01:19
task.cancel が呼び出されたときに、 download 関数の実装者は URLSessionTask を即時 cancel したいけど、それを実現するために使えるという。
01:21
Ideally translate NSURLErrorCancelled to CancellationError here
については、やっぱり Convention 上はキャンセル時は CancellationErrorthrow されるようにしたいという意識なのかな。ただ、 100% 保証は無理だから、やっぱり呼び出し側では as CancellationError で判別するのではなく Task.isCancelled が良さそう。
Avatar
koher 30-Aug-21 01:44 AM
一体どうすれば?(そして Proposal のコードに await が抜けてることに気付いた)
01:46
↓なら通ったけど、ちょっと・・・。そして onCancelSendable でない Box を渡せてしまってるのはなぜ???
func download(url: URL) async throws -> Data? { let urlSessionTask: Box<URLSessionTask> = .init() return try await withTaskCancellationHandler { return try await withUnsafeThrowingContinuation { continuation in let task = URLSession.shared.dataTask(with: url) { data, _, error in if let error = error { // Ideally translate NSURLErrorCancelled to CancellationError here continuation.resume(throwing: error) } else { continuation.resume(returning: data) } } task.resume() urlSessionTask.value = task } } onCancel: { urlSessionTask.value?.cancel() // runs immediately when cancelled } } final class Box<Value> { var value: Value? }
Avatar
shiz 30-Aug-21 03:22 AM
onCancelのクロージャで[urlSessionTask]をcapture listに入れる必要がありますかね?🤔
onCancel: { [urlSessionTask] in urlSessionTask?.cancel() // runs immediately when cancelled }
Sendableチェックはmainでも起きませんか?おそらくこのPRがrelease/5.5に入ってないからチェックされてないんじゃないかなーと思いました。 https://github.com/apple/swift/pull/38866 SwiftFiddleでやってみたらmainの場合warningが出ました。
/main.swift:21:7: warning: cannot use let 'urlSessionTask' with a non-sendable type 'Box<URLSessionTask>' from concurrently-executed code urlSessionTask.value?.cancel() // runs immediately when cancelled ^ /main.swift:25:13: note: generic class 'Box' does not conform to the `Sendable` protocol final class Box<Value> {
(edited)
Rework Sendable checking to be completely based on &quot;missing&quot; conformances, so that we can individually diagnose missing Sendable conformances based on both the module in which the...
Avatar
koher 30-Aug-21 07:23 PM
onCancelのクロージャで[urlSessionTask]をcapture listに入れる必要がありますかね?
capture list に入れても nil の状態で capture されるだけで変更が反映されなくないでしょうか?
19:28
おそらくこのPRがrelease/5.5に入ってないからチェックされてないんじゃないかな
なるほど。 Sendable のチェックはまだお預けなんですね・・・。
19:29
Sendable の status も↓ですしね。
Status: Accepted (2021-03-16)
https://github.com/apple/swift-evolution/blob/main/proposals/0302-concurrent-value-and-concurrent-closures.md
19:30
Structured Concurrency なんてまだ Active Review のまま😂 https://github.com/apple/swift-evolution/blob/main/proposals/0304-structured-concurrency.md
😂 1
Avatar
koher 30-Aug-21 08:10 PM
@MainActor も付けてないのに↓のコンパイルエラーになるのなぜ??そして Task.detached の代わりに Task.init を使うと起こらない・・・。 Version 13.0 beta 5 (13A5212g)
final class UserViewController: UIViewController { let userID: User.ID var user: User? ... override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) Task.detached(priority: .background) { [self] in do { let user = try await fetchUser(for: userID) self.user = user // ⛔ Property 'user' isolated to global actor 'MainActor' can not be mutated from a non-isolated context } catch { // エラーハンドリング } } } }
Avatar
koher 30-Aug-21 08:18 PM
UIViewController に付いてのか。
@MainActor class UIViewController : UIResponder
https://developer.apple.com/documentation/uikit/uiviewcontroller
20:19
Task.init だと MainActor 上で実行されるけど、 detached だとそうじゃないからエラーになってしまったと。
20:23
override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) Task.detached(priority: .background) { [self] in do { let user = try await fetchUser(for: userID) DispatchQueue.main.async { [self] in self.user = user } } catch { // エラーハンドリング } } }
20:23
↑で MainActor に戻したらいけたけど、 DispatchQueue.main よりもいい方法ないんだっけ?
20:25
DispatchQueue.main って型じゃないけど、どうやって MainActor と紐付いてるの?( DispatchQueue.global() だとコンパイルエラー)
20:26
よく考えたら Global Actor の Proposal ちゃんと読んでなかった。ここに答えがあるのかな・・・。 https://github.com/apple/swift-evolution/blob/main/proposals/0316-global-actors.md
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - swift-evolution/0316-global-actors.md at main · apple/swift-evolution
Avatar
rintaro 30-Aug-21 08:28 PM
extension UserViewController { func setUser(_ user: User?) { self.user = user } }
作っておいて await self.setUser(user) とか?
Avatar
koher 30-Aug-21 08:28 PM
お、↓でいけた。
override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) Task.detached(priority: .background) { @MainActor [self] in do { let user = try await fetchUser(for: userID) self.user = user } catch { // エラーハンドリング } } }
Avatar
Avatar
rintaro
extension UserViewController { func setUser(_ user: User?) { self.user = user } }
作っておいて await self.setUser(user) とか?
koher 30-Aug-21 08:29 PM
それって setUser も actor-isolated でダメじゃないですか?
20:30
await するのか。
Avatar
rintaro 30-Aug-21 08:30 PM
UserViewController のメソッドは暗黙で MainActor isolatedになるので、他の Actor コンテキストからは暗黙に async なので await で呼べると。
20:31
プロパティのセッタも暗黙 async になれば await self.user = user とかできるんだけど、そうなってないし、そうなっていない理由があるんじゃないかと。
Avatar
koher 30-Aug-21 08:32 PM
プロパティの async は getter only ですもんね、今のところ。
Avatar
rintaro 30-Aug-21 08:32 PM
Task.detached(priority: .background) { @MainActor [self] in って Task.init と実質かわらなくないです?
Avatar
Avatar
rintaro
Task.detached(priority: .background) { @MainActor [self] in って Task.init と実質かわらなくないです?
koher 30-Aug-21 08:35 PM
MainActor だけど Taskpriority.background っていうのはあり得るのかと思いましたが、 priority は queue ごとに決まっていてそんなことはない? DispatchQueuepriority って queue を作るときに決めますもんね。
20:38
うーん、 setUser を作るのもなぁ・・・。
DispatchQueue.main.async { self.user = user }
か、そうでなければ↓?
Task { @MainActor in self.user = user }
Avatar
rintaro 30-Aug-21 08:39 PM
とりあえず Task.init は現在の Actor コンテキストを引き継ぐと思うので 今回の場合は @MainActor in はいらないと思います。
20:40
await { @MainActor in self.user = user }()
🤔
Avatar
Avatar
rintaro
とりあえず Task.init は現在の Actor コンテキストを引き継ぐと思うので 今回の場合は @MainActor in はいらないと思います。
koher 30-Aug-21 08:43 PM
Task.init は現在の Actor コンテキストを引き継ぐと思うので 今回の場合は @MainActor in はいらない
↓みたいに Task.init ではなく Task.detached を挟んで context を引き継がないときなので MainActor に戻す必要があるかと。
override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) Task.detached(priority: .background) { [self] in do { let user = try await fetchUser(for: userID); Task { @MainActor in self.user = user } } catch { // エラーハンドリング } } }
Avatar
Avatar
koher
Task.init は現在の Actor コンテキストを引き継ぐと思うので 今回の場合は @MainActor in はいらない
↓みたいに Task.init ではなく Task.detached を挟んで context を引き継がないときなので MainActor に戻す必要があるかと。
override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) Task.detached(priority: .background) { [self] in do { let user = try await fetchUser(for: userID); Task { @MainActor in self.user = user } } catch { // エラーハンドリング } } }
rintaro 30-Aug-21 08:43 PM
あああ、ごめんなさい、読み違えてました
Avatar
koher 30-Aug-21 08:44 PM
await { @MainActor in self.user = user }()
これさっき似たようなことを試したときに await 付けないといけないことに気付いてなかったんですけど、そしたらコンパイラがクラッシュしました😅
😂 1
20:45
↓は通った。
override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) Task.detached(priority: .background) { [self] in do { let user = try await fetchUser(for: userID); await { @MainActor in self.user = user }() } catch { // エラーハンドリング } } }
Avatar
Avatar
koher
await { @MainActor in self.user = user }()
これさっき似たようなことを試したときに await 付けないといけないことに気付いてなかったんですけど、そしたらコンパイラがクラッシュしました😅
rintaro 30-Aug-21 08:47 PM
func foo() async { { @MainActor in }() }
でクラッシュ再現しました。報告しておきます
🙇‍♂️ 1
Avatar
koher 30-Aug-21 08:48 PM
この場合は Task.detached で作られた Task 上で実行されて、 Task { @MainActor in だと新しい Task 上で実行されるのが違いか。ただし、どちらでも main スレッド( DispatchQueue.main 上)で実行されると。
20:53
なんかよくわからなくなってきた・・・。 DispatchQueue はキューが priority を持ってるけど、 Swift Concurrency では actor (キューの保持者)ではなく Taskpriority を持っている。 Task が suspend されたときに resume される優先度が Taskpriority で決まると思ってたけど、 actor は suspend した Taskpriority に関わらずキューに突っ込んだ順に resume する?それとも MainActorDispatchQueue.main を使っている関係で Taskpriority を無視して前から処理する? (edited)
Avatar
shiz 30-Aug-21 10:12 PM
> capture list に入れても nil の状態で capture されるだけで変更が反映されなくないでしょうか?
ああ、そうですねwコンパイルできることしか考えてなかったです😅
(edited)
Avatar
shiz 30-Aug-21 10:25 PM
actor は suspend した Task の priority に関わらずキューに突っ込んだ順に resume する?
WWDCのセッションでこのように言っていたので、優先順位に合わせて入れ替えるものだと思っていました🤔
Since actors are designed for reentrancy, the runtime may choose to move the higher-priority item to the front of the queue, ahead of the lower-priority items. This way, higher-priority work could be executed first, with lower-priority work following later. This directly addresses the problem of priority inversion, allowing for more effective scheduling and resource utilization.
https://developer.apple.com/videos/play/wwdc2021/10254/?time=2160
それとも MainActor は DispatchQueue.main を使っている関係で Task の priority を無視して前から処理する?
DispatchQueue経由なので厳格に順番通りなんですかね...?🤔
(edited)
Dive into the details of Swift concurrency and discover how Swift provides greater safety from data races and thread explosion while...
Avatar
koher 31-Aug-21 03:47 AM
WWDCのセッションでこのように言っていたので、優先順位に合わせて入れ替えるものだと思っていました
なるほど、それなら普通の actor は入れ替えてくれそうな感じがしますね。
DispatchQueue経由なので厳格に順番通りなんですかね...?
DispatchQueueDispatchWorkItemqos を指定できるみたいですね。使ったことなかった。 https://developer.apple.com/documentation/dispatch/dispatchworkitem
03:48
そうすると MainActor でも priority を考慮してくれそう。
03:50
なら↓もありな可能性があるのかな?
override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) Task.detached(priority: .background) { @MainActor in do { let user = try await fetchUser(for: userID) self.user = user } catch { // エラーハンドリング } } }
@MainActor のクロージャ式が丸ごと↓の block に突っ込まれるイメージ?
DispatchQueue.main.async(DispatchWorkItem(qos: .background, block: /* ここ */))
(edited)
Avatar
shiz 31-Aug-21 05:21 AM
勘違いしているかもしれませんが...💦 DispatchQueue.mainはSerial Queueなので、qosが高いDispatchWorkItemが追加されても、前のDispatchWorkItemqos上げて先に実行してしまわないんでしょうか?(priority inversionが起きる?)
Avatar
kateinoigakukun 31-Aug-21 05:25 AM
ちゃんと話終えてないかもしれないですが、この辺の話ですか? https://github.com/apple/swift/blob/068291cba7199051bcd9e19aa3c1268a3c6b1e4a/stdlib/public/Concurrency/GlobalExecutor.cpp#L319-L328
05:26
We cannot safely elevate the priorities of work added to this queue using Dispatch's public API, but as discussed above, that is less important than avoiding performance problems.
Avatar
Avatar
shiz
勘違いしているかもしれませんが...💦 DispatchQueue.mainはSerial Queueなので、qosが高いDispatchWorkItemが追加されても、前のDispatchWorkItemqos上げて先に実行してしまわないんでしょうか?(priority inversionが起きる?)
omochimetaru 31-Aug-21 05:26 AM
その話まさにWWDCでスライドを見た気がします
05:27
後ろの高qosを消化するために前の待ちタスクが昇格する (edited)
Avatar
shiz 31-Aug-21 05:54 AM
ちゃんと話終えてないかもしれないですが、この辺の話ですか?
あ、そうですね。このコメントの話だと思います(難しくて完全に理解できているわけではありませんがw)
その話まさにWWDCでスライドを見た気がします
はい、WWDCのこの辺りで話されていました。 https://developer.apple.com/videos/play/wwdc2021/10254/?time=1984
Dive into the details of Swift concurrency and discover how Swift provides greater safety from data races and thread explosion while...
Avatar
shiz 31-Aug-21 09:24 PM
WWDCのセッションでこのように言っていたので、優先順位に合わせて入れ替えるものだと思っていました
そういえばactorでも実行中のTaskに関してはPriority Inversionが発生するとソースドキュメントに書いてありましたね https://github.com/apple/swift/blob/release/5.5-08092021/stdlib/public/Concurrency/Task.swift#L208 このテストがその挙動を表しているぽいですね👀 https://github.com/apple/swift/blob/main/test/Concurrency/Runtime/async_task_priority_current.swift#L11
(edited)
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.
Avatar
koher 01-Sep-21 01:13 AM
そうか、ちょっと勘違いしてました。並行にキューに入れたときにどの順番で突っ込まれたかは重要ではないから、優先度の高いアイテムはプライオリティに基づいて(たとえばバブルソートの要領で末尾から舐めて)適切な位置に挿入すればいいんじゃないかと思ってましたが、同じスレッドから順番にキューに入れた場合は順番が保証されていないと困る場合もあるから、キューに入っているアイテムの順番は入れ替えることはできなですね。なので、優先度の高いアイテムより前にあるアイテムの優先度を高めるしかないと。
👍 1
Avatar
omochimetaru 07-Sep-21 05:51 PM
The fourth review of SE-0304: Structured Concurrency has ended and the proposal has been accepted with modifications. Much of the fourth revision was about naming and the community was broadly positive about these changes, with discussion focused on a few specific points. The naming of the function suspend, that frees the task mid-function, wa...
🙌🏻 3
17:51
APIついに固まった
Avatar
omochimetaru 13-Sep-21 01:02 PM
Hey everyone! A few weeks ago I pitched Shared Storage for Property Wrappers, and TL;DR it was restructured into 3 other features. One of them, @expanded parameters, is what I'd like to get feedback on today. The updated proposal is on GitHub. Introduction Swift is a language that allows us to write expressive API interfaces. With features li...
13:03
関数の仮引数に付けられる新しいアトリビュート @expanded を追加する提案 これがついている引数は、その型の init の引数を、直接その関数の引数として渡せる。 (edited)
13:10
いいじゃんと思ったんだけど、フォーラム読んでたらjroseさんがstrongly againstしていて、書き込みを読んだらうーむ確かにと思えてきた
Avatar
kateinoigakukun 13-Sep-21 01:18 PM
Library evolutionの面で突っ込むの流石だなぁ
Avatar
omochimetaru 13-Sep-21 01:19 PM
たしかに。
Avatar
tarunon 23-Sep-21 11:39 AM
associatedtypeのあるprotocolをORTにした場合に、associatedtypeの部分を指定する方法って無いですよね
11:40
指定無しで推論もされない、つまりFoo<some Bar>みたいなことを実現する術が無いように見える (edited)
Avatar
Iceman 23-Sep-21 01:02 PM
protocol P { associatedtype Value } protocol Q: P where Value == Int {}
このQ を作るのをサボりたいってことですか?
Avatar
tarunon 23-Sep-21 01:37 PM
Valueの型がややこしくなるからORTにしたい場合に、その外側にPがある場合に出来なくなるなという話です
Avatar
Iceman 23-Sep-21 01:50 PM
なるほど。これだと手で型を書かないといけないので複雑な型には使えないですね
Avatar
omochimetaru 24-Sep-21 09:30 AM
@swift-5.5.3
protocol Base { func foo() func bar() } protocol Derived: Base { func foo() override func bar() }
Avatar
Avatar
omochimetaru
@swift-5.5.3
protocol Base { func foo() func bar() } protocol Derived: Base { func foo() override func bar() }
swift55 BOT 24-Sep-21 09:30 AM
no output
Avatar
omochimetaru 24-Sep-21 09:30 AM
@swift-5.5.3 -warn-implicit-overrides
protocol Base { func foo() func bar() } protocol Derived: Base { func foo() override func bar() }
Avatar
Avatar
omochimetaru
@swift-5.5.3 -warn-implicit-overrides
protocol Base { func foo() func bar() } protocol Derived: Base { func foo() override func bar() }
swift55 BOT 24-Sep-21 09:30 AM
stderr:
<stdin>:7:10: warning: implicit override should be marked with 'override' or suppressed with '@_nonoverride' func foo() ^ override <stdin>:2:10: note: overridden declaration is here func foo() ^
Avatar
omochimetaru 24-Sep-21 09:30 AM
Avatar
rintaro 24-Sep-21 05:21 PM
https://github.com/apple/swift/commit/f8e53d912954e63f967fc6e0450731a40f4cc08b このコミットのためにつくられたっぽいですね
Add the -warn-implicit-overrides flag when building the standard library and overlays, so that each protocol member that overrides a member of an inherited protocol will produce a warning unless ...
17:23
public protocol BaseP { func foo() func bar() } public protocol DerivedP: BaseP { override func foo() @_nonoverride func bar() } public struct Concrete: DerivedP { public func foo() {} public func bar() {} }
のときの witness table が
sil_witness_table Concrete: DerivedP module test { base_protocol BaseP: Concrete: BaseP module test method #DerivedP.bar: <Self where Self : DerivedP> (Self) -> () -> () : @$s4test8ConcreteVAA8DerivedPA2aDP3baryyFTW // protocol witness for DerivedP.bar() in conformance Concrete } sil_witness_table Concrete: BaseP module test { method #BaseP.foo: <Self where Self : BaseP> (Self) -> () -> () : @$s4test8ConcreteVAA5BasePA2aDP3fooyyFTW // protocol witness for BaseP.foo() in conformance Concrete method #BaseP.bar: <Self where Self : BaseP> (Self) -> () -> () : @$s4test8ConcreteVAA5BasePA2aDP3baryyFTW // protocol witness for BaseP.bar() in conformance Concrete }
@_nonoverride と明示された requirement は別の witness になる。
Avatar
omochimetaru 24-Sep-21 05:27 PM
ふむふむ、つまり、名前は同じだけど、名前が違うかのようにテーブルエントリが作られて
17:27
conformするメソッドは両方に登録される
17:28
nonoverrideの方はアンスコがついてるけど、overrideは普通のキーワードなのは、
17:28
同じ名前ならオーバーライドになるのは従来の普通の挙動だから?
17:30
A protocol requirement marked ‘override’ only makes sense when the declaration is needed to help associated type inference, which is why the ‘override’ annotations correlate so closely with ABI FIXMEs.
17:30
associated typeの推論のヒントになる・・・?
Avatar
rintaro 24-Sep-21 05:34 PM
具体例がほしいですね。。。
Avatar
omochimetaru 24-Sep-21 05:34 PM
BidirectionalCollection.index(_:offsetBy:) is the most obvious example, because the BidirectionalCollection ’s version of index(_:offsetBy:) allows negative indices. RandomAccessCollection ’s version is also marked @_nonoverride because it is required to be asymptotically faster than the Collection or BidirectionalCollection versions.
17:35
nonoverrideの方は最も明らかな例としてなんか書いてあるけどわからねえ・・・
Avatar
rintaro 24-Sep-21 05:35 PM
@_nonoverride に関しては
public protocol BaseP { func foo() func bar() } public extension BaseP { func foo() { print("BaseP.foo()") } func bar() { print("BaseP.bar()") } } public protocol DerivedP: BaseP { override func foo() @_nonoverride func bar() } public extension DerivedP { func foo() { print("DerivedP.foo()") } func bar() { print("DerivedP.bar()") } } public struct Concrete: DerivedP {}
Avatar
omochimetaru 24-Sep-21 05:36 PM
テーブルエントリが別になる事はわかったけどそれにより何が嬉しいのかがわからない
Avatar
rintaro 24-Sep-21 05:36 PM
みたいなときに、
sil_witness_table Concrete: DerivedP module test { base_protocol BaseP: Concrete: BaseP module test method #DerivedP.bar: <Self where Self : DerivedP> (Self) -> () -> () : @$s4test8ConcreteVAA8DerivedPA2aDP3baryyFTW // protocol witness for DerivedP.bar() in conformance Concrete } sil_witness_table Concrete: BaseP module test { method #BaseP.foo: <Self where Self : BaseP> (Self) -> () -> () : @$s4test8ConcreteVAA5BasePA2aDP3fooyyFTW // protocol witness for BaseP.foo() in conformance Concrete method #BaseP.bar: <Self where Self : BaseP> (Self) -> () -> () : @$s4test8ConcreteVAA5BasePA2aDP3baryyFTW // protocol witness for BaseP.bar() in conformance Concrete }
こうなるんだけど
Avatar
omochimetaru 24-Sep-21 05:36 PM
はい
Avatar
rintaro 24-Sep-21 05:37 PM
この状態で 最後の protocol witness for BaseP.bar() を呼び出す方法がわからないので、
何が嬉しいのかがわからない
です笑
😆 1
Avatar
omochimetaru 24-Sep-21 05:38 PM
<T: BaseP>で受け取った時はそっちが使われそうです。
Avatar
rintaro 24-Sep-21 05:39 PM
@swift-5.5.3
public protocol BaseP { func foo() func bar() } public extension BaseP { func foo() { print("BaseP.foo()") } func bar() { print("BaseP.bar()") } } public protocol DerivedP: BaseP { override func foo() @_nonoverride func bar() } public extension DerivedP { func foo() { print("DerivedP.foo()") } func bar() { print("DerivedP.bar()") } } public struct Concrete: DerivedP { } func testBase<T: BaseP>(x: T) { x.foo() x.bar() } func testDerived<T: DerivedP>(x: T) { x.foo() x.bar() } testBase(x: Concrete()) testDerived(x: Concrete())
Avatar
Avatar
rintaro
@swift-5.5.3
public protocol BaseP { func foo() func bar() } public extension BaseP { func foo() { print("BaseP.foo()") } func bar() { print("BaseP.bar()") } } public protocol DerivedP: BaseP { override func foo() @_nonoverride func bar() } public extension DerivedP { func foo() { print("DerivedP.foo()") } func bar() { print("DerivedP.bar()") } } public struct Concrete: DerivedP { } func testBase<T: BaseP>(x: T) { x.foo() x.bar() } func testDerived<T: DerivedP>(x: T) { x.foo() x.bar() } testBase(x: Concrete()) testDerived(x: Concrete())
swift55 BOT 24-Sep-21 05:39 PM
DerivedP.foo() DerivedP.bar() DerivedP.foo() DerivedP.bar()
Avatar
omochimetaru 24-Sep-21 05:45 PM
@swift-5.5.3
protocol Base { func foo() } protocol Derived: Base { @_nonoverride func foo() } struct Impl: Derived { @_implements(Base, foo()) func foo1() { print("Impl.foo1") } @_implements(Derived, foo()) func foo2() { print("Impl.foo2") } } func callBase<T: Base>(_ x: T) { x.foo() } func callDerived<T: Derived>(_ x: T) { x.foo() } callBase(Impl()) callDerived(Impl())
Avatar
Avatar
omochimetaru
@swift-5.5.3
protocol Base { func foo() } protocol Derived: Base { @_nonoverride func foo() } struct Impl: Derived { @_implements(Base, foo()) func foo1() { print("Impl.foo1") } @_implements(Derived, foo()) func foo2() { print("Impl.foo2") } } func callBase<T: Base>(_ x: T) { x.foo() } func callDerived<T: Derived>(_ x: T) { x.foo() } callBase(Impl()) callDerived(Impl())
swift55 BOT 24-Sep-21 05:46 PM
Impl.foo1 Impl.foo2
Avatar
omochimetaru 24-Sep-21 05:46 PM
呼び分けできた。
Avatar
tarunon 24-Sep-21 05:46 PM
これは嬉しい場面ありそう
Avatar
omochimetaru 24-Sep-21 05:47 PM
BidirectionalCollection.index(_:offsetBy:) は、
17:48
offsetとして与えられた回数だけ前(や後ろ)にオフセットをループしないといけないけど
17:49
RandomAccessCollection.index(_:offetBy:) は、一気にオフセットしたインデックスを作ってアクセスできる
17:49
けど・・・テーブルが別になっててほしい理由がわからん・・・
17:49
BidirectionalCollectionとして見ているときであっても、実装がRandomAccessCollectionなのであれば、RandomAccessCollectionの早い実装を使いたいのだから、テーブルエントリは同一で良くないか??
Avatar
rintaro 24-Sep-21 05:49 PM
<C: BidirectionalCollection> に RandomAccessCollection が渡ってきたときに BidirectionalCollection の実装を呼びたい場面てなんだろう?
Avatar
Avatar
rintaro
<C: BidirectionalCollection> に RandomAccessCollection が渡ってきたときに BidirectionalCollection の実装を呼びたい場面てなんだろう?
omochimetaru 24-Sep-21 05:50 PM
これがいま最大の謎ですね 全然obvious exampleじゃねえ・・・
17:51
それとも、逆の方向で問題が起きるということか? RandomAccessCollectionなのに、BidirectionalCollectionのしょぼい実装が入ってしまうことがある? (edited)
Avatar
rintaro 24-Sep-21 05:54 PM
public protocol BaseP { func foo() func bar() } public extension BaseP { func foo() { print("BaseP.foo()") } func bar() { print("BaseP.bar()") } } public protocol DerivedP: BaseP { override func foo() @_nonoverride func bar() } public struct Concrete: DerivedP {}
でエラーにならないのでそういうわけでもなさそう
Avatar
omochimetaru 24-Sep-21 05:57 PM
うーむ。手元で試してみたけどそういう事も特に起こらなさそう。
17:58
When a protocol restates a requirement from its inherited protocol, track that as an override the same way we do with overrides in classes. Such overrides are recorded in the AST but are omitted fr...
17:59
プルリクにもうちょっと説明があるな
18:00
Rolling this out in the standard library shrinks the size of the standard library binary by 196k.
Avatar
rintaro 24-Sep-21 06:02 PM
これはー、もともとのデフォルト挙動が @_nonoverride 相当だったのを override 相当にすることによって witness table が小さくなってサイズ削減できたって話っぽいですよね。
Avatar
omochimetaru 24-Sep-21 06:03 PM
ふむふむ。
18:03
そもそも overridenonoverride も付けない場合で、サブプロトコルで同じ名前をrequirementsに書くことができて、その場合テーブルエントリが別にできるわけですね。
18:04
で、このPRでは、
18:05
18:05
overrideを付けてるところと、nonoverrideを付けてるところがあるから、
18:06
そのままこれまでどおり別エントリであることを明示的にしたnonoverrideの方は別に何もかわってなくって、 このパッチではoverrideをつけたところに関して、テーブルエントリがなくなるからバイナリサイズが減ったよということか
18:06
そうすると、なんでそもそも、同じ名前のテーブルエントリを作ってたんだ??
18:08
This makes restating protocol requirements in inheriting protocols ABI-neutral, so we can restate protocol requirements to influence associated type inference without baking those decisions into the ABI.
18:14
@swift-5.5.3
protocol Base { func foo() } protocol Derived: Base { func foo() } struct Impl: Derived { @_implements(Base, foo()) func foo1() { print("foo1") } @_implements(Derived, foo()) func foo2() { print("foo2") } } func callBase<T: Base>(_ x: T) { x.foo() } func callDerived<T: Derived>(_ x: T) { x.foo() } callBase(Impl()) callDerived(Impl())
Avatar
Avatar
omochimetaru
@swift-5.5.3
protocol Base { func foo() } protocol Derived: Base { func foo() } struct Impl: Derived { @_implements(Base, foo()) func foo1() { print("foo1") } @_implements(Derived, foo()) func foo2() { print("foo2") } } func callBase<T: Base>(_ x: T) { x.foo() } func callDerived<T: Derived>(_ x: T) { x.foo() } callBase(Impl()) callDerived(Impl())
swift55 BOT 24-Sep-21 06:14 PM
foo1 foo1
Avatar
omochimetaru 24-Sep-21 06:14 PM
逆ですね。どちらも付けなかった場合の挙動は、overrideです。
18:15
↑のコードで、Derived.foo@_nonoverride をつけると、2行目の出力が foo2 に変わる。
18:21
When a protocol restates a requirement from its inherited protocol, track that as an override the same way we do with overrides in classes.
プロトコル要求を再定義したとき、クラスのオーバライドと同じ仕組みで紐付けられる。
Such overrides are recorded in the AST but are omitted from the witness table itself.
このオーバライドはASTとして記録されているがwitness talbeでは消える。
This makes restating protocol requirements in inheriting protocols ABI-neutral,
継承先プロトコルでの再定義がABIに影響を与えない(netutral)ので
so we can restate protocol requirements to influence associated type inference without baking those decisions into the ABI.
これらの決定をABIに焼き込むことなしに、associated type推論を促すために、プロトコル要求の再定義をすることができる。
18:22
ここまでは意味がまあわかる、associated type推論はずっと壊れがちだったから、これをうまく動かすために、継承先protocolでメソッドを再定義するという技があって、たとえ再定義してもオーバライド判定によりテーブルに影響はないからABI上の副作用はないと。
18:24
As part of this, introduce tools that allow us to audit all of the restated protocol requirements within the standard library, via a warning new warning flag (-warn-implicit-overrides) to warn about such requirements, as well as an appropriate suppression mechanism (override to treat it as an override, @_nonoverride to give it a new witness table entry).
で、このオーバーライドがちゃんと効いてることをチェックできるように、ちゃんとマーキングした上で、マーキングなしでオーバライドしてたら通知する警告を作ったよと・・・そこもわかる。
(edited)
18:26
Only those restated requirements that are meant to have a semantic effect,
再定義した要求において意味上の影響を意図しているものだけは
like BidirectionalCollection.index(_:offsetBy:),
たとえば BidirectionalCollection.indexなど
should use @_nonoverride,
は、nonoverrideを付けたほうが良い
because it commits us to having that entry in the witness table forever.
なぜならテーブルエントリを永遠に保持することを約束してくれるから。
(edited)
18:27
言ってることはわかるけどやっぱりBidirectionalCollectionでそれをやりたい根本的な理由がわからないな。
18:28
しかもこれ、2018年9月の話なんですよね。何年も気づかなかった。。
Avatar
shiz 26-Sep-21 09:40 PM
AsyncSequenceでOptionalを扱いたい場合、nextの戻り値の型をOptionalのOptionalにしなければいけないのは、ループの終わり記号としてのnilと、要素としてのnilを区別するために仕方がないんですかね?(AsyncStream との比較のためにあえてAsyncSequence 使ってます) ちょっと不思議な気もしたのですが、nextの定義にOptionalが付いているのでそういうものなんですね...  改めて考えたらIteratorProtocol と同じですね(失礼しましたmm)。
mutating func next() async throws -> Self.Element?
struct IntGenerator: AsyncSequence { typealias Element = Int? var strings: [String] struct AsyncIterator: AsyncIteratorProtocol { var current = 1 var strings: [String] fileprivate var index = 0 mutating func next() async -> Int?? { // <- ここ guard index < strings.count else { return nil } let string = strings[index] index += 1 return Int(string) } } func makeAsyncIterator() -> AsyncIterator { AsyncIterator(strings: strings) } } Task { let strings: [String] = ["1", "a", "2"] for await i in IntGenerator(strings: strings) { print(i) } }
Optional(1) nil Optional(2)
(edited)
Avatar
Avatar
shiz
AsyncSequenceでOptionalを扱いたい場合、nextの戻り値の型をOptionalのOptionalにしなければいけないのは、ループの終わり記号としてのnilと、要素としてのnilを区別するために仕方がないんですかね?(AsyncStream との比較のためにあえてAsyncSequence 使ってます) ちょっと不思議な気もしたのですが、nextの定義にOptionalが付いているのでそういうものなんですね...  改めて考えたらIteratorProtocol と同じですね(失礼しましたmm)。
mutating func next() async throws -> Self.Element?
struct IntGenerator: AsyncSequence { typealias Element = Int? var strings: [String] struct AsyncIterator: AsyncIteratorProtocol { var current = 1 var strings: [String] fileprivate var index = 0 mutating func next() async -> Int?? { // <- ここ guard index < strings.count else { return nil } let string = strings[index] index += 1 return Int(string) } } func makeAsyncIterator() -> AsyncIterator { AsyncIterator(strings: strings) } } Task { let strings: [String] = ["1", "a", "2"] for await i in IntGenerator(strings: strings) { print(i) } }
Optional(1) nil Optional(2)
(edited)
koher 27-Sep-21 12:59 AM
Java 等の言語だと nullable の入れ子ができないので、 Iterator の API が hasNextnext に分かれていて、まず hasNext で存在を確認してから next を呼ぶという手順になっていますね。その点、 next だけで済ませられる Swift の設計はシンプルだと思います。
👍🏻 1
Avatar
Avatar
koher
Java 等の言語だと nullable の入れ子ができないので、 Iterator の API が hasNextnext に分かれていて、まず hasNext で存在を確認してから next を呼ぶという手順になっていますね。その点、 next だけで済ませられる Swift の設計はシンプルだと思います。
shiz 27-Sep-21 03:46 AM
なるほど、ありがとうございます!確かにそう考えるとシンプルですね!
👍 1
Avatar
rintaro 30-Sep-21 03:00 AM
https://forums.swift.org/t/declarative-string-processing-overview/52459 Regex + 文字列パターンマッチングDSL
Declarative String Processing Overview Introduction String processing is hard and the current affordances provided by the Swift Standard Library are underpowered. We propose adding two new declarative string processing APIs—a familiar Regex literal and a more powerful Pattern result builder—to help make Swift string processing fast and easy. T...
👀 2
Avatar
tarunon 30-Sep-21 03:00 AM
オッ
03:04
そういえばSwift5.5で追加されたAttributedStringは結構良かったですね
03:11
他の言語でこういうRegexの外側にラッパーがあるみたいな構成が、公式から提供されてる例ってありましたっけ
03:11
広義的にはperlの拡張regexとかもこの類と考えれるのかな
Avatar
rintaro 30-Sep-21 03:16 AM
ちょうど Raku の Grammar https://forums.swift.org/t/declarative-string-processing-overview/52459/13 が引き合いにだされましたね (edited)
Avatar
omochimetaru 30-Sep-21 04:11 AM
func graphemeBreakPropertyData( forLine line: String ) -> (scalars: ClosedRange<Unicode.Scalar>, property: Unicode.GraphemeBreakProperty)? { line .match(/([0-9A-F]+)(?:\.\.([0-9A-F]+))?\s*;\s(\w+).*/)? .captures.flatMap { (l, u, p) in guard let property = Unicode.GraphemeBreakProperty(p) else { return nil } let scalars = Unicode.Scalar(hex: l)! ... Unicode.Scalar(hex: u ?? l)! return (scalars, property) } }
04:12
l, u, p の3要素タプルなのは正規表現パターンと対応しているのか。これはいいなあ。
04:13
func graphemeBreakPropertyData( forLine line: String ) -> (scalars: ClosedRange<Unicode.Scalar>, property: Unicode.GraphemeBreakProperty)? { line.match { OneOrMore(.hexDigit).capture { Unicode.Scalar(hex: $0) } Optionally { ".." OneOrMore(.hexDigit).capture { Unicode.Scalar(hex: $0) } } OneOrMore(.whitespace) ";" OneOrMore(.whitespace) OneOrMore(.word).capture(GraphemeBreakProperty.init) Repeat(.anyCharacter) }?.captures.map { (lower, upper, property) in let scalars = lower ... (upper ?? lower) return (scalars, property) } }
04:13
ResultBuilder記法もあるのね
Avatar
omochimetaru 30-Sep-21 05:30 AM
これってResultBuilderになってるメリットあるのかな? 普通に配列で書けそうに見える。カンマが要らなくなってるだけじゃない?
Avatar
tarunon 30-Sep-21 05:40 AM
ResultBuilderを使うメリットがある場合は
05:41
1. 複雑な型の構築 2. 1において必要となる複雑な型のピースをexpressionによる暗黙的変換の実現で見えなくする
05:41
の2つで、どちらかは使ってるんじゃないだろうか
Avatar
omochimetaru 30-Sep-21 05:42 AM
たしかに、 captures.map { (lower, upper, property) の3要素タプルになってるところで
05:42
.match の中に書いてある3つの .capture があることと対応しているのか。
05:42
配列じゃできないな。
Avatar
tarunon 30-Sep-21 05:42 AM
これは生成されている型は雪だるま式のヤバメgenericsだと思うよ
Avatar
omochimetaru 30-Sep-21 05:43 AM
どうやってるんだろう、難しそうだ
05:43
自由なツリー構造になる型パラメータを線形スキャンしてcaptureがある回数をタプル型に変換させないといけない
Avatar
tarunon 30-Sep-21 05:45 AM
要素があるか無しかの2択の畳み込みなら、
05:45
まあ出来なくもないかな?って感じはする
Avatar
omochimetaru 30-Sep-21 05:46 AM
The Swift Programming Language. Contribute to ishantheperson/swift development by creating an account on GitHub.
05:46
フォーラムにプロトタイプ実装のリンクとしてここが貼ってあるけど見つからない
05:49
ブランチが違うのか
05:52
The Swift Programming Language. Contribute to ishantheperson/swift development by creating an account on GitHub.
05:54
The Swift Programming Language. Contribute to ishantheperson/swift development by creating an account on GitHub.
05:54
diffが出せた。ResultBuilder実装はまだ存在しないっぽい。
Avatar
norio_nomura 30-Sep-21 05:54 AM
An early experimental general-purpose pattern matching engine for Swift. - GitHub - apple/swift-experimental-string-processing: An early experimental general-purpose pattern matching engine for Swift.
Avatar
omochimetaru 30-Sep-21 05:54 AM
05:57
うーんここにもなさそう?
Avatar
norio_nomura 30-Sep-21 05:58 AM
なかった
05:59
*OneOrMoreって書かれてて心配になる。
😲 1
Avatar
omochimetaru 30-Sep-21 05:59 AM
05:59
ZeroOrMore
Avatar
shiz 02-Oct-21 10:30 AM
Appleのドキュメントに記載されている例を使ってAsyncStreamの挙動を調べていたのですが、(1)のループの後にfinishを呼ぶとonTerminationのコールバックが呼ばれてcancel扱いになるのですが、これってこういうものなのでしょうか? なんとなく「値の出力が全部終わってfinishしたらなぜかcancel処理が走った」みたいな印象を受けたのでどうなのかなあと思いまして😅
func hoge() async { let digits = AsyncStream(Int.self) { continuation in Task.detached { for digit in 0..<10 { // (1) continuation.yield(digit) } continuation.finish() continuation.onTermination = { @Sendable finished in if case .cancelled = finished { print("cancel") // 呼ばれる } } } } for await digit in digits { print(digit) } }
https://developer.apple.com/documentation/swift/asyncstream
(edited)
Avatar
tarunon 02-Oct-21 10:36 AM
多分なんですけど、finishを呼ぶ前にonTerminationを定義しておかないと
10:36
AsyncSequenceが完了した後でonTerminationに登録される、ってなってて変になってる気がする (edited)
10:37
この場合、onTerminationの発火はAsyncSequenceが解放された方をトリガーに発火していて、キャンセル扱いになってしまってるんじゃないでしょうか
Avatar
shiz 02-Oct-21 10:53 AM
ありがとうございます!前に持ってきたらfinishedに変わりました!ただfinishedが出力されるタイミングが毎回変わるのがまだよくわかってないです…
func hoge() async { let digits = AsyncStream(Int.self) { continuation in Task.detached { for digit in 0..<10 { continuation.yield(digit) } continuation.onTermination = { @Sendable finished in switch finished { case .finished: print("finished") // タイミングがバラバラ case .cancelled: print("cancel") @unknown default: break } } continuation.finish() } } for await digit in digits { print(digit) } }
(edited)
Avatar
tarunon 02-Oct-21 10:58 AM
https://discord.com/channels/291054398077927425/291054454793306112/890879652363657227 この辺りで議論したんですが、yieldで渡した値がawaitの宣言側に渡されるのは非同期的なんですよね。一方でcontinuation.finishのコールは、awaitの宣言のない箇所なので、同期的になってるんじゃないかと。
10:59
AsyncSequenceを他の言語のyield相当として使うことは出来ないので、非同期的な箇所と同期的な箇所の順番が保証されることも、同様に無いと考えています
Avatar
shiz 02-Oct-21 11:02 AM
あーなるほど。その辺りの議論がきちんと理解できてませんでした💦 ありがとうございます🙇🏻‍♂️後片付けみたいな用途には使えないのか... (edited)
Avatar
koher 13-Oct-21 03:51 AM
"Swift Concurrency チートシート" の Case 20 ( MainActor )で
final class UserViewController: UIViewController { private let state: UserViewState ... override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) state.loadUser() } }
としてるの、ダメでは?これだと loadUser の非同期処理が終わるまで viewDidAppear を抜けられない・・・。 https://zenn.dev/koher/articles/swift-concurrency-cheatsheet#%F0%9F%92%BC-case-20-(mainactor)%3A-%E5%85%B1%E6%9C%89%E3%81%95%E3%82%8C%E3%81%9F%E7%8A%B6%E6%85%8B%E3%81%AE%E5%A4%89%E6%9B%B4%EF%BC%88%E3%83%A1%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%AC%E3%83%83%E3%83%89%E4%B8%8A%E3%81%A7%E3%81%AE%E5%87%A6%E7%90%86%EF%BC%89
Avatar
tarunon 13-Oct-21 03:52 AM
loadUserの実装次第では
03:53
Taskを生成して非同期処理してるなら抜けれますね
Avatar
koher 13-Oct-21 03:58 AM
自分で書いたサンプルコード見たらそうなってました。混乱してた・・・。
func loadUser() { Task { do { user = try await fetchUser(for: userID) } catch { // エラーハンドリング } } }
04:00
@MainActor で意図せず async であるべきメソッドが同期的に呼べてヤバいケースがあるんじゃないかと考えてたんだけど、 fetchUser@MainActor とは関係のない async 関数だから、ここで await が必須になって、 loadUserasync をつけなきゃとなった時点で気付くか。よかった。 (edited)
Avatar
tarunon 13-Oct-21 04:01 AM
そうですね、基本問題ないはず
👍 1
Avatar
omochimetaru 15-Oct-21 02:22 PM
@swift-nightly
protocol P {} struct S: P {} func makeS() -> S { S() } let f1 = makeS as () -> P print("f1 ok") if let f2 = makeS as? () -> P { print("f2 ok") } else { print("f2 ng") }
Avatar
Avatar
omochimetaru
@swift-nightly
protocol P {} struct S: P {} func makeS() -> S { S() } let f1 = makeS as () -> P print("f1 ok") if let f2 = makeS as? () -> P { print("f2 ok") } else { print("f2 ng") }
swiftNightly BOT 15-Oct-21 02:22 PM
f1 ok f2 ng
stderr:
<stdin>:8:19: warning: runtime conversion from '() -> S' to '() -> P' is not supported; cast always fails if let f2 = makeS as? () -> P { ^ <stdin>:8:19: note: consider using 'as' coercion instead if let f2 = makeS as? () -> P { ^~~ as <stdin>:8:8: warning: value 'f2' was defined but never used; consider replacing with boolean test if let f2 = makeS as? () -> P { ~~~~^~~~~ ~~~ is
Avatar
omochimetaru 15-Oct-21 02:22 PM
as は通るけど as? は失敗する、という事があるらしい。
Avatar
kateinoigakukun 15-Oct-21 02:23 PM
Anyに一回キャストするといけません?
Avatar
omochimetaru 15-Oct-21 02:24 PM
@swift-nightly
protocol P {} struct S: P {} func makeS() -> S { S() } let f1 = makeS as () -> P print("f1 ok") if let f2 = makeS as Any as? () -> P { print("f2 ok") } else { print("f2 ng") }
Avatar
Avatar
omochimetaru
@swift-nightly
protocol P {} struct S: P {} func makeS() -> S { S() } let f1 = makeS as () -> P print("f1 ok") if let f2 = makeS as Any as? () -> P { print("f2 ok") } else { print("f2 ng") }
swiftNightly BOT 15-Oct-21 02:24 PM
f1 ok f2 ng
stderr:
<stdin>:8:8: warning: value 'f2' was defined but never used; consider replacing with boolean test if let f2 = makeS as Any as? () -> P { ~~~~^~~~~ ~~~ is
Avatar
kateinoigakukun 15-Oct-21 02:24 PM
ダメだ
Avatar
omochimetaru 15-Oct-21 02:24 PM
こう?同じ結果になる
Avatar
kateinoigakukun 15-Oct-21 02:26 PM
動的キャスト強制すればなんか変わるかなと思ったんですけど
Avatar
omochimetaru 20-Oct-21 08:59 AM
Xcode13のSwift、 Swift パッケージに、 CodableConfiguration という新要素が勝手に追加されてる。 https://developer.apple.com/documentation/swift/keyeddecodingcontainer/3766918-decode
09:00
swift-evolution飛ばして体験版(?)が出るやつ
Avatar
tarunon 20-Oct-21 09:00 AM
Just having a look at the documentation of CodableConfiguration. Maybe "the types are the documentation" is taken a little bit too far in this case? 😅
09:00
これだw
Avatar
omochimetaru 20-Oct-21 09:01 AM
CodableConfigurationFoundation だからセーフか
Avatar
tarunon 20-Oct-21 09:01 AM
ググっても情報少なすぎて笑う
Avatar
omochimetaru 20-Oct-21 09:02 AM
Swift.KeyedDecodingContainer.func decode<T, C>(_: CodableConfiguration<T?, C>.Type, forKey key: KeyedDecodingContainer<K>.Key) throws -> CodableConfiguration<T?, C> where T : DecodableWithConfiguration, T : EncodableWithConfiguration, C : DecodingConfigurationProviding, C : EncodingConfigurationProviding, T.DecodingConfiguration == C.DecodingConfiguration, T.EncodingConfiguration == C.EncodingConfiguration
09:02
いや、これは、protocol側に生えてるよな・・・?
09:02
extensionでいける?
Avatar
tarunon 20-Oct-21 09:02 AM
Learn what the new CodableWithConfiguration type is and how you can use it to create better decoding and encoding code.
09:02
解説記事だ
Avatar
omochimetaru 20-Oct-21 09:05 AM
KeyedDecodingContainerstruct だから、
09:05
Foundation から extension で生やす分には
09:05
Swift モジュールに影響はないのか。
Avatar
Iceman 20-Oct-21 09:05 AM
例によってオーバーロードのマジックで処理を差し込んでそう
09:06
引数のインターフェースは同じだけどGenericsの型パラの数で優先度あげてそう
Avatar
tarunon 20-Oct-21 09:06 AM
このハック、公式で使われてるの見る度に「やってんな〜」って思う
Avatar
omochimetaru 20-Oct-21 09:06 AM
あ、これ引数の数同じなのか 普通 タイプを指定するところに、 CodableConfiguration に包んだタイプを指定する形か。ややこしー。
09:07
機能としては便利なやつな気配がするので後で↑の解説をよく読んでみる。
Avatar
omochimetaru 20-Oct-21 09:11 AM
ちょっと前にフォーラムで
09:12
Codableの困り募集スレがあったのは
09:12
この機能リリースをぶちこむ時になるべく世のニーズにもすり合わせようとしたのかも
Avatar
omochimetaru 09-Nov-21 02:08 PM
The core team is going through the backlog of proposed evolution proposals, and would like to put forward SE-0330: Conditionals in Collections for review by the community. The review begins now and runs through November 19th, 2021. The proposal is authored by @johnno1962. Reviews are an important part of the Swift evolution process. All revie...
14:09
配列リテラルの途中で #if 書ける案
14:09
#if より if 書きたいなと思った。
Avatar
Kishikawa Katsumi 09-Nov-21 02:34 PM
The most notable use case for this is conditional inclusion of tests for the Swift version of XCTest though it is certain to have other applications in practice allowing data to be tailored to production/development environments, architecture or build configuration.
まあわかるけどどうかな。それ以外のユースケースあるかな。
Avatar
tarunon 09-Nov-21 02:45 PM
if書くのはResultBuilderで頑張ればそれっぽいの出来る
😯 1
Avatar
koher 09-Nov-21 02:53 PM
↓この辺りで話してたやつですね。 < ResultBuilder で頑張れば https://discord.com/channels/291054398077927425/375206337937801216/740039408903782452
Avatar
Kishikawa Katsumi 09-Nov-21 02:59 PM
Dictionaryは確かにたまにある気がする。具体的なケース思い出せないけど
Avatar
koher 09-Nov-21 03:00 PM
Optional な値で、存在するときだけ ArrayDictionary に入れたいとか。
Avatar
Kishikawa Katsumi 09-Nov-21 03:07 PM
あるような気がする。
15:08
Process(シェルスクリプトの呼び出しとか)に渡すOptionをArrayで渡すときとかそんな感じかも。
15:10
これはTypeScriptだけど
const args = [ 'xcresulttool', 'get', '--path', this.bundlePath, '--format', 'json' ] if (reference) { args.push('--id') args.push(reference) }
こういう感じだな。
Avatar
koher 09-Nov-21 03:12 PM
そういうやつですね。
Avatar
Kishikawa Katsumi 09-Nov-21 03:15 PM
まあArrayなら + と三項演算子でそれっぽく書けるか。。。?
Avatar
omochimetaru 09-Nov-21 04:07 PM
Optionalなときは .compact() で取り除いてる
Avatar
Kishikawa Katsumi 09-Nov-21 04:10 PM
どっちが読みやすいかな
Avatar
omochimetaru 17-Nov-21 03:35 PM
Hello Swift Community, The review of SE-0326: Multi-statement closure parameter/result type inference has completed. Feedback was light but positive, and the core team has accepted this proposal. The core team recognizes that the language change has the slight possibility of requiring source changes, but that the benefits brought by this chang...
👀 1
15:35
大物がacceptした、やったー
Avatar
Iceman 17-Nov-21 05:08 PM
おお、これって今まで一行クロージャにしかなかった型推論用の型パラの伝播が複数行クロージャにも対応するって感じですか?
Avatar
omochimetaru 17-Nov-21 05:09 PM
はい 複数行クロージャの型も中身のコードから推論可能になります
Avatar
Iceman 17-Nov-21 05:09 PM
これはすごい
Avatar
omochimetaru 17-Nov-21 05:09 PM
仕組みとしてはResultBuilderのために導入された型推論の進化を応用してる
Avatar
Iceman 17-Nov-21 05:10 PM
RxやCombineの書き心地がめちゃくちゃ改善しますね
Avatar
omochimetaru 17-Nov-21 05:10 PM
あれは結局複数の文から全体として一つの型を求めてるから。
Avatar
Iceman 17-Nov-21 05:10 PM
ELFも
Avatar
omochimetaru 17-Nov-21 05:11 PM
そうなんすよね guardが出てきて3文になった瞬間に型の明記が必要なのがだるかった
17:12
まあそのへん全部async awaitに行けば解決するから適用領域はめっちゃ減りそうなタイミングだけどもw
Avatar
Iceman 17-Nov-21 05:13 PM
それは確かにw
Avatar
omochimetaru 17-Nov-21 05:15 PM
クソデカconcurrencyの着地が見えてきてまたSwiftの多様なアプデがいろいろ出てきそうだな
Avatar
omochimetaru 26-Nov-21 03:35 AM
もしかしてSE-0299によってprotocolをネームスペースとして使えるようになった?
protocol P {} extension P { // static funcが書けるようになった static func foo() -> Int { 0 } /* インナータイプは作れないけど struct Inner {} */ } /* typealiasできるので実質可能? */ struct _P_Inner {} extension P { typealias Inner = _P_Inner } print(P.Inner())
Avatar
Iceman 26-Nov-21 03:37 AM
// static funcが書けるようになった
ここにちょっとテクニックが必要で、ダミーのPを何かしら用意しないと呼べないんですよね
Avatar
omochimetaru 26-Nov-21 03:38 AM
ほんまや
Avatar
Iceman 26-Nov-21 03:38 AM
struct InvalidP: P {} extension P where Self == InvalidP {}
とすることで foo を呼べます
03:39
それも P.foo() じゃなくて func f(_ p: P) に対して f(.foo()) という形になるので多少ややこしい
Avatar
omochimetaru 26-Nov-21 03:39 AM
ドット記法の場合だけか。じゃあネームスペースにはならんなあ
Avatar
yutailang0119 26-Nov-21 03:59 AM
テクい
Avatar
Iceman 26-Nov-21 06:37 AM
extension Never: P {} extension P where Self == Never {}
のほうが安全だということに気づいた
Avatar
omochimetaru 26-Nov-21 06:44 AM
propertyWrapperに空のinitがあるときだけは変数の型宣言が省略できる気がするんですけど、そういうもんでしたっけ。
Avatar
tarunon 26-Nov-21 06:45 AM
型宣言というか変数そのものをなくせる(から、連鎖的に型も消えて見える)という話かな?
Avatar
omochimetaru 26-Nov-21 06:48 AM
変数そのものを無くせる?
Avatar
tarunon 26-Nov-21 06:48 AM
@Bar var bar = 1
コレは通るんじゃないかしら
Avatar
omochimetaru 26-Nov-21 06:48 AM
ほんとだ、通った
06:48
あ〜そういう事・・・?
Avatar
tarunon 26-Nov-21 06:48 AM
init() は引数なし、あるいはVoidなので
06:49
そういうこと
Avatar
omochimetaru 26-Nov-21 06:49 AM
型宣言を代入文の右辺値からの推論で省略しているパターンの発展形で、 右辺値が空の式として推論できるから成立するみたいな・・・
Avatar
tarunon 26-Nov-21 06:50 AM
WrappedValueがGenericsなら、型の省略は許されなくなりそうだ
06:51
規格には言及が無さそうなんだよね
@propertyWrapper struct StringDictionary { var wrappedValue: [String: String] } @StringDictionary var d1. // infers Dictionary<String, String> @StringDictionary var d2: Dictionary // infers <String, String>
↑なんかいろいろ怪しいサンプルコードはある
(edited)
Avatar
tarunon 26-Nov-21 06:51 AM
やばそうだなw
Avatar
omochimetaru 26-Nov-21 06:52 AM
そもそも「型が決まっててもinitが空なら右辺値を省略できる」なんて概念は他に無いし怪しいなあ
Avatar
Iceman 26-Nov-21 06:52 AM
普通にプロパティ宣言する場合は右辺値が空の式じゃなくても成立するから微妙にかみあってない感じがする
Avatar
omochimetaru 26-Nov-21 06:52 AM
var x: Int? は右辺値要らないけど・・・
Avatar
Avatar
Iceman
普通にプロパティ宣言する場合は右辺値が空の式じゃなくても成立するから微妙にかみあってない感じがする
omochimetaru 26-Nov-21 06:52 AM
あ〜いや、そうか
06:53
そうすると @Bar var b が駄目なのが話と違うような気もしてきたな
Avatar
tarunon 26-Nov-21 06:53 AM
@swift-5.5.3
var a: Void
Avatar
Avatar
tarunon
@swift-5.5.3
var a: Void
swift55 BOT 26-Nov-21 06:53 AM
no output
Avatar
tarunon 26-Nov-21 06:53 AM
事実上コレと一緒ってことかと
06:54
Intは実はBarから推論されてるんだよね。で、空initはVoidを受け取るというPropertyWrapperの仕様が組み合わさった結果として
Avatar
omochimetaru 26-Nov-21 06:54 AM
@swift-5.5.3
var a: Void var b: Int
Avatar
Avatar
omochimetaru
@swift-5.5.3
var a: Void var b: Int
swift55 BOT 26-Nov-21 06:54 AM
no output
Avatar
tarunon 26-Nov-21 06:54 AM
怪奇なコードがpopしてる
06:54
あれ
06:55
@swift-5.5.3
let a: Void
Avatar
Avatar
tarunon
@swift-5.5.3
let a: Void
swift55 BOT 26-Nov-21 06:55 AM
no output
Avatar
tarunon 26-Nov-21 06:55 AM
これこれ
Avatar
omochimetaru 26-Nov-21 06:55 AM
@swift-5.5.3
func foo() { let a: Void let b: Int }
Avatar
Avatar
omochimetaru
@swift-5.5.3
func foo() { let a: Void let b: Int }
swift55 BOT 26-Nov-21 06:55 AM
stderr:
<stdin>:2:7: warning: immutable value 'a' was never used; consider replacing with '_' or removing it let a: Void ^ _ <stdin>:3:7: warning: immutable value 'b' was never used; consider replacing with '_' or removing it let b: Int ^ _
Avatar
omochimetaru 26-Nov-21 06:55 AM
?w
Avatar
tarunon 26-Nov-21 06:55 AM
あれれ〜〜〜〜〜
Avatar
omochimetaru 26-Nov-21 06:56 AM
@swift-5.4.3 @swift-5.3.3 @swift-5.2.5
func foo() { let a: Void let b: Int }
Avatar
Avatar
omochimetaru
@swift-5.4.3 @swift-5.3.3 @swift-5.2.5
func foo() { let a: Void let b: Int }
swift54 BOT 26-Nov-21 06:56 AM
stderr:
<stdin>:2:7: warning: immutable value 'a' was never used; consider replacing with '_' or removing it let a: Void ^ _ <stdin>:3:7: warning: immutable value 'b' was never used; consider replacing with '_' or removing it let b: Int ^ _
Avatar
Avatar
omochimetaru
@swift-5.4.3 @swift-5.3.3 @swift-5.2.5
func foo() { let a: Void let b: Int }
swift52 BOT 26-Nov-21 06:56 AM
stderr:
<stdin>:2:7: warning: immutable value 'a' was never used; consider replacing with '_' or removing it let a: Void ^ _ <stdin>:3:7: warning: immutable value 'b' was never used; consider replacing with '_' or removing it let b: Int ^ _
Avatar
Avatar
omochimetaru
@swift-5.4.3 @swift-5.3.3 @swift-5.2.5
func foo() { let a: Void let b: Int }
swift53 BOT 26-Nov-21 06:56 AM
stderr:
<stdin>:2:7: warning: immutable value 'a' was never used; consider replacing with '_' or removing it let a: Void ^ _ <stdin>:3:7: warning: immutable value 'b' was never used; consider replacing with '_' or removing it let b: Int ^ _
Avatar
omochimetaru 26-Nov-21 06:56 AM
右辺値って要らなかったのか
Avatar
tarunon 26-Nov-21 06:56 AM
使ってなければ宣言なくても怒られなくなった?
06:56
@swift-5.5.3
let a: Void print(a)
Avatar
Avatar
tarunon
@swift-5.5.3
let a: Void print(a)
swift55 BOT 26-Nov-21 06:56 AM
()
Avatar
omochimetaru 26-Nov-21 06:56 AM
@swift-5.5.3
func foo() { let a: Void let b: Int print(a) print(b) }
(edited)
Avatar
Avatar
omochimetaru
@swift-5.5.3
func foo() { let a: Void let b: Int print(a) print(b) }
(edited)
swift55 BOT 26-Nov-21 06:57 AM
exit status: 1 with stderr:
<stdin>:5:9: error: constant 'b' used before being initialized print(b) ^ <stdin>:3:7: note: constant defined here let b: Int ^
Avatar
tarunon 26-Nov-21 06:57 AM
よかった
Avatar
omochimetaru 26-Nov-21 06:57 AM
Voidは右辺値無しで初期化されるのね
06:57
Intは未初期化使用が検出
06:57
たしかにこの挙動が関係してる感じはあるな
Avatar
tarunon 26-Nov-21 06:57 AM
で、PropertyWrapperの無引数initはVoid扱いなんじゃない?っていう
Avatar
omochimetaru 26-Nov-21 06:58 AM
たしかに初期値で @Foo var a = () って書くのは変だな
06:58
= () は何もない時にそう書いてる扱いがされるって感じか
07:00
@propertyWrapper struct Bar { var wrappedValue: Int init(wrappedValue: Int = 0) { self.wrappedValue = wrappedValue } } struct S { @Bar var b }
07:00
↑これもいけた、なるほどね
Avatar
tarunon 26-Nov-21 07:01 AM
ここで、IntがGenericsになると
Avatar
omochimetaru 26-Nov-21 07:01 AM
そうか、Optionalっぽいやつの場合にこれがあれば、 init(wrappedValue: T? = nil) がいけるのか
Avatar
tarunon 26-Nov-21 07:01 AM
型推論が通らなくなるから、完全省略が出来なくなるよ
Avatar
omochimetaru 26-Nov-21 07:01 AM
まあそのときでも @Bar<Int> var b これはいけるでしょ (edited)
Avatar
nanasi 26-Nov-21 07:11 AM
SwiftUIのEnvironmentは変数の型宣言を省略した解説をよく見ますね
07:11
@Environment(\.colorScheme) var colorScheme みたいな
Avatar
nanasi 26-Nov-21 07:25 AM
この場合はpropertyWrapper側に明示的にイニシャライザを付けて呼び出しているから別の話でしたね
Avatar
Iceman 09-Dec-21 07:42 AM
onAppear の中はコンパイラ的にはMainActorっぽい(viewModel2のメソッド呼び出しにawaitがいらないので)けど明示的に @MainActor がついてないほうはコンテキストの引き継ぎが行われなくて、メインスレッド警告がでている?
07:47
あ、このサンプルコードは-warn-concurrency ついてなかったから気づかなかったけどちゃんと警告でてた・・( Cannot use parameter 'self' with a non-sendable type 'ViewModel1' from concurrently-executed code ) Taskの中でawaitが起こるときにselfが明示的なactor contextを持っているかを確認してあればそのactor contextにスイッチするという感じなのかな
Avatar
koher 09-Dec-21 07:49 AM
そうか。 selfSendable じゃないからそもそも Task.init のクロージャに渡せないのか。
07:53
Actor Context は func ごとに静的に決定されるもので、クロージャの場合、条件を満たせば( non-@Sendable または Task.init )引き継がれる?
07:54
ある Actor Context から同期的に呼び出された関数の中は Actor Context を持たないという理解でいいのかな?
Avatar
Iceman 09-Dec-21 07:57 AM
現象を見る限りはそうだといえそうですね
08:01
await の箇所ごとにコンパイラが見える範囲まで最寄りのActor Contextを探して、見つからなかったらそのままasync側のコンテキストに着地してそう
Avatar
koher 09-Dec-21 08:03 AM
async 側のコンテクストも存在しないのかな。結果的に async API の呼び出し先依存のスレッドで実行されるにしても、そこでさらにクロージャを書いたからといってそのコンテクストが引き継がれるとかはないと。
08:05
actor Foo { func bar() -> Int { // Thread 2 & Foo の Actor Context 42 } }
let foo = Foo() Task { // Thread 1 let x = await foo.bar() // Thread 2 (ただし Foo の Actor Context ではない) print(x) Task { // Thread 3 ( Foo の Actor Context は引き継がない) print(x) } }
(edited)
Avatar
Iceman 09-Dec-21 08:06 AM
この場合はコンパイラがTaskのネストを探索してFooに到達できそうなのでコンテキストが引き継がれるかも?
08:12
func global() async -> Int { return await withCheckedContinuation { c in DispatchQueue.global().async { c.resume(returning: 42) } } } @MainActor final class Foo { func start() { Task { let x = await global() print(x, Thread.isMainThread) // 42 true Task { let x = await global() print(x, Thread.isMainThread) // 42 true } } } }
これは引き継がれてそうです
08:13
(もちろんMainActorを外したらどちらもfalseになる)
Avatar
koher 09-Dec-21 08:13 AM
↑だと start が Main Actor の Actor Context を持つので、その中に書かれたクロージャには(条件を満たせば) Actor Context が引き継がれますね。
Avatar
Iceman 09-Dec-21 08:15 AM
あ、コードが修正されていた
Avatar
koher 09-Dec-21 08:15 AM
あ、すみません。 bar を呼び出すのに foo を書き忘れてたので・・・。
08:16
await bar()await foo.bar() の修正と、 foo の宣言を最初に追加しました。
Avatar
Iceman 09-Dec-21 08:17 AM
actor Bar { func bar() -> Int { DispatchQueue.main.sync { 42 } } } final class Foo { func start() { let bar = Bar() Task { let x = await bar.bar() print(x, Thread.isMainThread) // 42 false Task { let x = await bar.bar() print(x, Thread.isMainThread) // 42 false } } } }
これはfalseだ。async元のコンテキストを引き継いでるのではなく無のコンテキストにスイッチしてるのかな
Avatar
koher 09-Dec-21 08:18 AM
試してないけど多分↓になると思います。
@MainActor final class Bar { func bar() -> Int { 42 } } final class Foo { func start(bar: Bar) { Task { print(Thread.isMainThread) // 42 false let x = await bar.bar() print(x, Thread.isMainThread) // 42 true Task { print(Thread.isMainThread) // 42 false let x = await bar.bar() print(x, Thread.isMainThread) // 42 true } } } }
(edited)
Avatar
Iceman 09-Dec-21 08:18 AM
Call to main actor-isolated initializer 'init()' in a synchronous nonisolated context
08:18
Bar がinit()できないですね・・
Avatar
koher 09-Dec-21 08:19 AM
外から与えるように修正しましたw
Avatar
Iceman 09-Dec-21 08:19 AM
実行したら全部falseでした
Avatar
koher 09-Dec-21 08:20 AM
えー、そうなのか?
08:20
Fooactor になってないですよね?
08:20
Task.init 自体がコンテクストを持つのかな?
Avatar
Iceman 09-Dec-21 08:20 AM
雑ですが
08:22
呼び出し先のスレッドをそのまま使うことはなくて、コンテキストが未定義の場合は未定義用の無コンテキストを使うみたいですね
Avatar
koher 09-Dec-21 08:28 AM
import SwiftUI @MainActor struct ContentView: View { let bar = Bar() var body: some View { Text("Hello, world!") .onAppear { Foo().start(bar: bar) } } } @MainActor final class Bar { func bar() -> Int { print("bar", Thread.isMainThread) return 42 } } final class Foo { func start(bar: Bar) { Task { print("1", Thread.isMainThread, ObjectIdentifier(Thread.current)) let x = await bar.bar() print("2", Thread.isMainThread, ObjectIdentifier(Thread.current), x) Task { print("3", Thread.isMainThread, ObjectIdentifier(Thread.current)) let x = await bar.bar() print("4", Thread.isMainThread, ObjectIdentifier(Thread.current), x) Task.detached { print("5", Thread.isMainThread, ObjectIdentifier(Thread.current)) let x = await bar.bar() print("6", Thread.isMainThread, ObjectIdentifier(Thread.current), x) } } } } }
1 false ObjectIdentifier(0x0000600001348780) bar true 2 false ObjectIdentifier(0x0000600001319580) 42 3 false ObjectIdentifier(0x0000600001319580) bar true 4 false ObjectIdentifier(0x0000600001348780) 42 5 false ObjectIdentifier(0x0000600001319580) bar true 6 false ObjectIdentifier(0x0000600001348780) 42
08:29
bar はたしかにメインスレッドで実行されているのと
08:30
1 と 2 が異なるスレッドで実行されていることから、 Task は Actor Context を持つわけではなさそう。 Actor Context がない場合も await 先が結果を返したスレッドでそのまま実行されるわけではなく、また別のスレッドに投入される?
08:32
↑も、 1 と 2 が同じスレッドで実行されることもあるけど(その方が多い)、それは節約されてるだけで、 1 と 2 が同じである保証はないと。
Avatar
Iceman 09-Dec-21 08:34 AM
無のコンテキストは複数あるみたいですが、シミュレーターだと2つで実機だともっとたくさんあるみたいな話をどこかで見ました
😇 1
Avatar
koher 09-Dec-21 08:41 AM
とりあえず、 Actor のメソッド中の最後の suspension point の後と、( Actor Context がないときの)呼び出し元の await の後は同期的だと思ってましたけど、それは違うと(どのスレッドで実行されるかわからない)。 Actor Context は静的に解決されると考えて、それ以外に想定外なところはなさそう。
👍 1
Avatar
omochimetaru 09-Dec-21 11:31 AM
anyプロポーザル読み終わった。良さそう。 心配なのはSwift6への自動マイグレーションだけだ。
11:32
心配してもしょうがないしみんなベータ期間に頑張ってチャレンジして報告しよう、でしかない
Avatar
omochimetaru 18-Feb-22 04:29 AM
@Icemanhttps://discord.com/channels/291054398077927425/430242233468452865/944056010585284649 で実験してるやつ 現場としては swift-nio で 2019年に発生してるんだけど https://github.com/apple/swift-nio/issues/1257 調べてたらこの既知の問題として整理されてた https://bugs.swift.org/browse/SR-14719
04:30
@usableFromInline internal struct S { @usableFromInline internal var a: Int @inlinable internal init() { self.a = 0 } }
04:30
a.swift:8:16: error: 'self' used before 'self.init' call or assignment to 'self' self.a = 0 ^ a.swift:9:5: error: 'self.init' isn't called on all paths before returning from initializer } ^
04:31
struct S@frozen にするとビルドできるようになるんだけど
04:32
「フィールドレイアウトが固定されていないのに init@inlinable だと、レイアウト変化後に、埋め込まれた古い init が正しく動作しないからおかしい」 というのが根底の話で
04:32
https://bugs.swift.org/browse/SR-14783 そういう診断メッセージを出したいというチケットになってた
Avatar
quesera2 19-Feb-22 04:05 AM
await中の状態をassertしたいときに、ちょっとRunLoopが回ってほしいという用途でTask.yield()使ってみたらうまくいけたんですけれど、合法的な使い方なのか怪しい…
async let result: () = viewModel.fetchRepository() await Task.yield() XCTAssertEqual(viewModel.repositories, []) stubApiClient.continue() // resumeで値を返却させる await result XCTAssertEqual(viewModel.repositories.count, 1)
Avatar
omochimetaru 19-Feb-22 04:33 AM
考え方はあってると思いますけどお行儀は良く無いですね
04:34
1回のyieldで期待したところまで処理が進むのかが、このコードからは保証されないですし。
04:36
これ最初のfetchRepositoryはasync letではなく普通にawaitしたらダメなんですか?
Avatar
quesera2 19-Feb-22 04:37 AM
上のコードだとわかりにくいのですけれど、await中にだけ変化するパラメータをassertしたいというケースを考えていました
04:38
たとえばプログレスを表示するみたいなパラメータがあって、await前と後はfalseなんですけれど、awaitの中でだけはtrueになるのをテストしたい、みたいなニーズになります
04:39
yield使うのはコード読んだ人が混乱するしあまりよくなさそうですね…
Avatar
omochimetaru 19-Feb-22 04:39 AM
あーfetch直後だけどawaitするまでの状態を確認したいってことですかね
Avatar
quesera2 19-Feb-22 04:39 AM
ですです
Avatar
omochimetaru 19-Feb-22 04:40 AM
これ逆に、repositoriesに対するassertが、fetchの開始より先に評価されてしまう可能性がありそう (edited)
04:41
stub.continueをするまで値が来てないことは保証できているのか
04:42
Task.yieldがなくても
04:42
狙ったテストシナリオが動くようにできそうに思うんですが
04:42
これが無いと何の処理が止まってるんですか?
Avatar
quesera2 19-Feb-22 04:46 AM
StubのAPIリポジトリでその場で結果を返してしまうと、await中の状態に対するassertionが書けないと考えていて、疑似コードですけれどこういう感じで値を返すのを遅延させている感じです
func fetchRepositories(userName: String) async throws -> [FooItem] {         // ここで値を返すとawait中の検証ができない return try await withCheckedThrowingContinuation { continuation in self.continuation = continuation } } func `continue`() { self.continuation.resume(returning: expectResult) }
04:47
Task.yield() がない場合、await内の処理がまったく進まないので、上のコードだと支障ないんですけれど、内部で値を変えているものが未反映になる感じですね
04:48
やりたいこととしてはこういう感じになります(こっちのほうがわかりやすかった)
XCTAssertFalse(viewModel.showProgress) async let result: () = viewModel.fetchRepository() await Task.yield() XCTAssertTrue(viewModel.showProgress) // ここを検証したい stubApiClient.continue() // resumeで値を返却させる await result XCTAssertFalse(viewModel.showProgress)
Avatar
omochimetaru 19-Feb-22 04:52 AM
うーんとつまり、 viewModel.fetchRepository の処理が動きはじめて viewModel.showPregress になったが、stubAPIClient.continue の呼び出しがまだされていない 時刻で、状態をassertしたいが、
04:53
async let の後に Task.yield が無い場合、 viewModel.fetchRepository の処理がまだ開始していない時刻に assert が処理してしまうってことですよね?
Avatar
quesera2 19-Feb-22 04:54 AM
わかりにくくてすみません、その理解であっています
Avatar
omochimetaru 19-Feb-22 04:54 AM
その場合は、「viewModel.fetchRepository の処理が動き始めるのを待機する」ロジックを明確に書くのが良いと思います。
04:55
おそらく、 viewModel.fetchRepository の中で、 StubAPIClient.fetchRepository を呼ぶようになってますよね、なので、
04:55
StubAPIClient に、 fetchRepository が呼ばれたら返ってくる await property を生やすのが良いんじゃないでしょうか
04:56
つまりテストコードとしては
04:56
XCTAssertFalse(viewModel.showProgress) async let result: () = viewModel.fetchRepository() await stubAPIClient.willFetchRepository XCTAssertTrue(viewModel.showProgress) stubApiClient.continue() await result XCTAssertFalse(viewModel.showProgress)
04:57
こう書けるようにする。
Avatar
quesera2 19-Feb-22 04:58 AM
なるほど、こちらのほうが自明になりますね
Avatar
omochimetaru 19-Feb-22 04:58 AM
はい。特定のタイミングで状態を検証したいという、シナリオの意図がコードで表現できるし、 Task.yield 1回だと期待した状態まで進行しない懸念も消せます (edited)
Avatar
rintaro 25-Feb-22 10:07 PM
withCString(:_) とか withUnsafeBytes(:_) をリストで扱いたいと思って、つまり
let array: [String] = [...] array.with(each: String.withCString) { cStrings/*: [UnsafePointer<CChar>] */ in cFunctionReceivingCStringArray(cStrings) }
こういうのがやりたくて、邪悪なものを生み出してしまった。
extension BidirectionalCollection { func with<U, R>( each mapFn: (Element) -> ((U) throws -> R) throws -> R, _ fn: ([U]) throws -> R ) rethrows -> R { try withoutActuallyEscaping(fn) { fn in try withoutActuallyEscaping(mapFn) { mapFn in var stash: [U] = [] stash.reserveCapacity(count) let closure = reversed().reduce({ try fn(stash) }) { closure, elem in { try mapFn(elem)() { val in stash.append(val) return try closure() } } } return try closure() } } } }
(edited)
Avatar
nanasi 14-Mar-22 09:34 AM
@available(macOS 12.3, iOS 15.4, watchOS 8.5, tvOS 15.4, *) public protocol CodingKeyRepresentable
となっているものの適合時に@available付けなくても何も言われず、下位バージョンだと以前のままArray扱いになってしまうみたいですね…
Avatar
Iceman 14-Mar-22 09:43 AM
そうなんですよね。結局Dictionaryの実装が動的にCodingKeyRepresentableを見に行くのでコンパイル時についてるだけじゃ意味ないっていう
Avatar
nanasi 14-Mar-22 02:03 PM
結構待ち望んでいたんですが、実際に使えるのは当分先ですね…
Avatar
omochimetaru 31-Mar-22 06:14 AM
Hello Swift Community, The review of SE-0345 "if let shorthand for shadowing an existing optional variable" ended on March 22, 2022. The Core Team has decided to accept the proposal. Both the pitch and review threads for this proposal were very active, with well over 200 posts each. The Core Team would like to address a few of the discussion po...
06:14
if let 採択
06:18
commonly rejected list が覆されたから、じゃああれもやりたい、って話題が出そうだなー
Avatar
koher 31-Mar-22 08:30 AM
それ思った。
Exported 12,094 message(s)